diff --git a/Meta/Lagom/CMakeLists.txt b/Meta/Lagom/CMakeLists.txt index a22b0396dd4..58f60dbb0a6 100644 --- a/Meta/Lagom/CMakeLists.txt +++ b/Meta/Lagom/CMakeLists.txt @@ -630,16 +630,6 @@ if (BUILD_LAGOM) SKIP_RETURN_CODE 1) # Tests that are not LibTest based - # test-crypto - add_executable(test-crypto_lagom ../../Userland/Utilities/test-crypto.cpp) - set_target_properties(test-crypto_lagom PROPERTIES OUTPUT_NAME test-crypto) - target_link_libraries(test-crypto_lagom LagomCore LagomTLS LagomCrypto LagomLine) - add_test( - NAME Crypto - COMMAND test-crypto_lagom test -t -s google.com --ca-certs-file ../../Base/etc/ca_certs.ini - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - # Shell file(GLOB SHELL_TESTS CONFIGURE_DEPENDS "../../Userland/Shell/Tests/*.sh") foreach(TEST_PATH ${SHELL_TESTS}) diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 6127e5b4d33..16372b89c82 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -153,7 +153,6 @@ target_link_libraries(tac LibMain) target_link_libraries(su LibCrypt LibMain) target_link_libraries(tar LibArchive LibCompress) target_link_libraries(telws LibProtocol LibLine) -target_link_libraries(test-crypto LibCrypto LibTLS LibLine) target_link_libraries(test-fuzz LibCore LibGemini LibGfx LibHTTP LibIPC LibJS LibMarkdown LibShell) target_link_libraries(test-imap LibIMAP LibMain) target_link_libraries(test-pthread LibThreading) diff --git a/Userland/Utilities/test-crypto.cpp b/Userland/Utilities/test-crypto.cpp deleted file mode 100644 index ee5d2d4d712..00000000000 --- a/Userland/Utilities/test-crypto.cpp +++ /dev/null @@ -1,3005 +0,0 @@ -/* - * Copyright (c) 2020, the SerenityOS developers. - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char* secret_key = "WellHelloFreinds"; -static const char* suite = nullptr; -static const char* filename = nullptr; -static const char* server = nullptr; -static const char* ca_certs_file = "/etc/ca_certs.ini"; -static int key_bits = 128; -static bool binary = false; -static bool interactive = false; -static bool run_tests = false; -static int port = 443; -static bool in_ci = false; - -static struct timeval start_time { - 0, 0 -}; -static bool g_some_test_failed = false; -static bool encrypting = true; - -constexpr const char* DEFAULT_DIGEST_SUITE { "HMAC-SHA256" }; -constexpr const char* DEFAULT_CHECKSUM_SUITE { "CRC32" }; -constexpr const char* DEFAULT_HASH_SUITE { "SHA256" }; -constexpr const char* DEFAULT_CIPHER_SUITE { "AES_CBC" }; -constexpr const char* DEFAULT_SERVER { "www.google.com" }; - -static Vector s_root_ca_certificates; - -// listAllTests -// Cipher -static int aes_cbc_tests(); -static int aes_ctr_tests(); -static int aes_gcm_tests(); - -// Hash -static int md5_tests(); -static int sha1_tests(); -static int sha256_tests(); -static int sha384_tests(); -static int sha512_tests(); - -// Authentication -static int hmac_md5_tests(); -static int hmac_sha256_tests(); -static int hmac_sha512_tests(); -static int hmac_sha1_tests(); -static int ghash_tests(); - -// Public-Key -static int rsa_tests(); - -// TLS -static int tls_tests(); - -// Big Integer -static int bigint_tests(); - -// Checksum -static int adler32_tests(); -static int crc32_tests(); - -// stop listing tests - -static void print_buffer(ReadonlyBytes buffer, int split) -{ - if (split > 0) - out("{:>{}hex-dump}", buffer, split); - else - out("{:hex-dump}", buffer); -} - -static Core::EventLoop g_loop; - -static int run(Function fn) -{ - if (interactive) { - auto editor = Line::Editor::construct(); - editor->initialize(); - for (;;) { - auto line_result = editor->get_line("> "); - - if (line_result.is_error()) - break; - auto& line = line_result.value(); - - if (line == ".wait") { - g_loop.exec(); - } else { - fn(line.characters(), line.length()); - g_loop.pump(); - } - } - } else { - if (filename == nullptr) { - warnln("must specify a filename"); - return 1; - } - if (!Core::File::exists(filename)) { - warnln("File does not exist"); - return 1; - } - auto file = Core::File::open(filename, Core::OpenMode::ReadOnly); - if (file.is_error()) { - warnln("Failed to open {}: {}", filename, file.error()); - return 1; - } - auto buffer = file.value()->read_all(); - fn((const char*)buffer.data(), buffer.size()); - g_loop.exec(); - } - return 0; -} - -static void tls(const char* message, size_t len) -{ - static RefPtr tls; - static ByteBuffer write {}; - if (!tls) { - tls = TLS::TLSv12::construct(nullptr); - tls->set_root_certificates(s_root_ca_certificates); - tls->connect(server ?: DEFAULT_SERVER, port); - tls->on_tls_ready_to_read = [](auto& tls) { - auto buffer = tls.read(); - if (buffer.has_value()) - out("{}", StringView { buffer->data(), buffer->size() }); - }; - tls->set_on_tls_ready_to_write([&](auto&) { - if (write.size()) { - tls->write(write); - write.clear(); - } - }); - tls->on_tls_error = [&](auto) { - g_loop.quit(1); - }; - tls->on_tls_finished = [&]() { - g_loop.quit(0); - }; - } - MUST(write.try_append(message, len)); - MUST(write.try_append("\r\n", 2)); -} - -static void aes_cbc(const char* message, size_t len) -{ - ReadonlyBytes buffer { message, len }; - // FIXME: Take iv as an optional parameter - auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()).release_value(); - - if (encrypting) { - Crypto::Cipher::AESCipher::CBCMode cipher( - StringView(secret_key).bytes(), - key_bits, - Crypto::Cipher::Intent::Encryption); - - auto enc = cipher.create_aligned_buffer(buffer.size()).release_value(); - auto enc_span = enc.bytes(); - cipher.encrypt(buffer, enc_span, iv); - - if (binary) - out("{}", StringView { enc_span.data(), enc_span.size() }); - else - print_buffer(enc_span, Crypto::Cipher::AESCipher::block_size()); - } else { - Crypto::Cipher::AESCipher::CBCMode cipher( - StringView(secret_key).bytes(), - key_bits, - Crypto::Cipher::Intent::Decryption); - auto dec = cipher.create_aligned_buffer(buffer.size()).release_value(); - auto dec_span = dec.bytes(); - cipher.decrypt(buffer, dec_span, iv); - outln("{}", StringView { dec_span.data(), dec_span.size() }); - } -} - -static void adler32(const char* message, size_t len) -{ - auto checksum = Crypto::Checksum::Adler32({ (const u8*)message, len }); - outln("{:#10X}", checksum.digest()); -} - -static void crc32(const char* message, size_t len) -{ - auto checksum = Crypto::Checksum::CRC32({ (const u8*)message, len }); - outln("{:#10X}", checksum.digest()); -} - -static void md5(const char* message, size_t len) -{ - auto digest = Crypto::Hash::MD5::hash((const u8*)message, len); - if (binary) - out("{}", StringView { digest.data, Crypto::Hash::MD5::digest_size() }); - else - print_buffer({ digest.data, Crypto::Hash::MD5::digest_size() }, -1); -} - -static void hmac_md5(const char* message, size_t len) -{ - Crypto::Authentication::HMAC hmac(secret_key); - auto mac = hmac.process((const u8*)message, len); - if (binary) - out("{}", StringView { mac.data, hmac.digest_size() }); - else - print_buffer({ mac.data, hmac.digest_size() }, -1); -} - -static void sha1(const char* message, size_t len) -{ - auto digest = Crypto::Hash::SHA1::hash((const u8*)message, len); - if (binary) - out("{}", StringView { digest.data, Crypto::Hash::SHA1::digest_size() }); - else - print_buffer({ digest.data, Crypto::Hash::SHA1::digest_size() }, -1); -} - -static void sha256(const char* message, size_t len) -{ - auto digest = Crypto::Hash::SHA256::hash((const u8*)message, len); - if (binary) - out("{}", StringView { digest.data, Crypto::Hash::SHA256::digest_size() }); - else - print_buffer({ digest.data, Crypto::Hash::SHA256::digest_size() }, -1); -} - -static void hmac_sha256(const char* message, size_t len) -{ - Crypto::Authentication::HMAC hmac(secret_key); - auto mac = hmac.process((const u8*)message, len); - if (binary) - out("{}", StringView { mac.data, hmac.digest_size() }); - else - print_buffer({ mac.data, hmac.digest_size() }, -1); -} - -static void sha384(const char* message, size_t len) -{ - auto digest = Crypto::Hash::SHA384::hash((const u8*)message, len); - if (binary) - out("{}", StringView { digest.data, Crypto::Hash::SHA384::digest_size() }); - else - print_buffer({ digest.data, Crypto::Hash::SHA384::digest_size() }, -1); -} - -static void sha512(const char* message, size_t len) -{ - auto digest = Crypto::Hash::SHA512::hash((const u8*)message, len); - if (binary) - out("{}", StringView { digest.data, Crypto::Hash::SHA512::digest_size() }); - else - print_buffer({ digest.data, Crypto::Hash::SHA512::digest_size() }, -1); -} - -static void hmac_sha512(const char* message, size_t len) -{ - Crypto::Authentication::HMAC hmac(secret_key); - auto mac = hmac.process((const u8*)message, len); - if (binary) - out("{}", StringView { mac.data, hmac.digest_size() }); - else - print_buffer({ mac.data, hmac.digest_size() }, -1); -} - -auto main(int argc, char** argv) -> int -{ - const char* mode = nullptr; - Core::ArgsParser parser; - parser.add_positional_argument(mode, "mode to operate in ('list' to see modes and descriptions)", "mode"); - - parser.add_option(secret_key, "Set the secret key (default key is 'WellHelloFriends')", "secret-key", 'k', "secret key"); - parser.add_option(key_bits, "Size of the key", "key-bits", 'b', "key-bits"); - parser.add_option(filename, "Read from file", "file", 'f', "from file"); - parser.add_option(binary, "Force binary output", "force-binary", 0); - parser.add_option(interactive, "REPL mode", "interactive", 'i'); - parser.add_option(run_tests, "Run tests for the specified suite", "tests", 't'); - parser.add_option(suite, "Set the suite used", "suite-name", 'n', "suite name"); - parser.add_option(server, "Set the server to talk to (only for `tls')", "server-address", 's', "server-address"); - parser.add_option(port, "Set the port to talk to (only for `tls')", "port", 'p', "port"); - parser.add_option(ca_certs_file, "INI file to read root CA certificates from (only for `tls')", "ca-certs-file", 0, "file"); - parser.add_option(in_ci, "CI Test mode", "ci-mode", 'c'); - parser.parse(argc, argv); - - StringView mode_sv { mode }; - if (mode_sv == "list") { - outln("test-crypto modes"); - outln("\tdigest - Access digest (authentication) functions"); - outln("\thash - Access hash functions"); - outln("\tchecksum - Access checksum functions"); - outln("\tencrypt -- Access encryption functions"); - outln("\tdecrypt -- Access decryption functions"); - outln("\ttls -- Connect to a peer over TLS 1.2"); - outln("\tlist -- List all known modes"); - outln("these modes only contain tests"); - outln("\ttest -- Run every test suite"); - outln("\tbigint -- Run big integer test suite"); - outln("\tpk -- Run Public-key system tests"); - return 0; - } - - if (mode_sv == "hash") { - if (suite == nullptr) - suite = DEFAULT_HASH_SUITE; - StringView suite_sv { suite }; - - if (suite_sv == "MD5") { - if (run_tests) - return md5_tests(); - return run(md5); - } - if (suite_sv == "SHA1") { - if (run_tests) - return sha1_tests(); - return run(sha1); - } - if (suite_sv == "SHA256") { - if (run_tests) - return sha256_tests(); - return run(sha256); - } - if (suite_sv == "SHA384") { - if (run_tests) - return sha384_tests(); - return run(sha384); - } - if (suite_sv == "SHA512") { - if (run_tests) - return sha512_tests(); - return run(sha512); - } - warnln("unknown hash function '{}'", suite); - return 1; - } - if (mode_sv == "checksum") { - if (suite == nullptr) - suite = DEFAULT_CHECKSUM_SUITE; - StringView suite_sv { suite }; - - if (suite_sv == "CRC32") { - if (run_tests) - return crc32_tests(); - return run(crc32); - } - if (suite_sv == "Adler32") { - if (run_tests) - return adler32_tests(); - return run(adler32); - } - warnln("unknown checksum function '{}'", suite); - return 1; - } - if (mode_sv == "digest") { - if (suite == nullptr) - suite = DEFAULT_DIGEST_SUITE; - StringView suite_sv { suite }; - - if (suite_sv == "HMAC-MD5") { - if (run_tests) - return hmac_md5_tests(); - return run(hmac_md5); - } - if (suite_sv == "HMAC-SHA256") { - if (run_tests) - return hmac_sha256_tests(); - return run(hmac_sha256); - } - if (suite_sv == "HMAC-SHA512") { - if (run_tests) - return hmac_sha512_tests(); - return run(hmac_sha512); - } - if (suite_sv == "HMAC-SHA1") { - if (run_tests) - return hmac_sha1_tests(); - } - if (suite_sv == "GHash") { - if (run_tests) - return ghash_tests(); - } - warnln("unknown hash function '{}'", suite); - return 1; - } - if (mode_sv == "pk") { - return rsa_tests(); - } - if (mode_sv == "bigint") { - return bigint_tests(); - } - if (mode_sv == "tls") { - if (!Core::File::exists(ca_certs_file)) { - warnln("Nonexistent CA certs file '{}'", ca_certs_file); - return 1; - } - auto config = Core::ConfigFile::open(ca_certs_file); - auto now = Core::DateTime::now(); - auto last_year = Core::DateTime::create(now.year() - 1); - auto next_year = Core::DateTime::create(now.year() + 1); - for (auto& entity : config->groups()) { - Certificate cert; - cert.subject.subject = entity; - cert.issuer.subject = config->read_entry(entity, "issuer_subject", entity); - cert.subject.country = config->read_entry(entity, "country"); - cert.not_before = Crypto::ASN1::parse_generalized_time(config->read_entry(entity, "not_before", "")).value_or(last_year); - cert.not_after = Crypto::ASN1::parse_generalized_time(config->read_entry(entity, "not_after", "")).value_or(next_year); - s_root_ca_certificates.append(move(cert)); - } - if (run_tests) - return tls_tests(); - return run(tls); - } - if (mode_sv == "test") { - encrypting = true; - aes_cbc_tests(); - aes_ctr_tests(); - aes_gcm_tests(); - - encrypting = false; - aes_cbc_tests(); - aes_ctr_tests(); - aes_gcm_tests(); - - md5_tests(); - sha1_tests(); - sha256_tests(); - sha384_tests(); - sha512_tests(); - - hmac_md5_tests(); - hmac_sha256_tests(); - hmac_sha512_tests(); - hmac_sha1_tests(); - - ghash_tests(); - - rsa_tests(); - - if (!in_ci) { - // Do not run these in CI to avoid tests with variables outside our control. - if (!Core::File::exists(ca_certs_file)) { - warnln("Nonexistent CA certs file '{}'", ca_certs_file); - return 1; - } - auto config = Core::ConfigFile::open(ca_certs_file); - auto now = Core::DateTime::now(); - auto last_year = Core::DateTime::create(now.year() - 1); - auto next_year = Core::DateTime::create(now.year() + 1); - for (auto& entity : config->groups()) { - Certificate cert; - cert.subject.subject = entity; - cert.issuer.subject = config->read_entry(entity, "issuer_subject", entity); - cert.subject.country = config->read_entry(entity, "country"); - cert.not_before = Crypto::ASN1::parse_generalized_time(config->read_entry(entity, "not_before", "")).value_or(last_year); - cert.not_after = Crypto::ASN1::parse_generalized_time(config->read_entry(entity, "not_after", "")).value_or(next_year); - s_root_ca_certificates.append(move(cert)); - } - tls_tests(); - } - - bigint_tests(); - - return g_some_test_failed ? 1 : 0; - } - encrypting = mode_sv == "encrypt"; - if (encrypting || mode_sv == "decrypt") { - if (suite == nullptr) - suite = DEFAULT_CIPHER_SUITE; - StringView suite_sv { suite }; - - if (StringView(suite) == "AES_CBC") { - if (run_tests) - return aes_cbc_tests(); - - if (!Crypto::Cipher::AESCipher::KeyType::is_valid_key_size(key_bits)) { - warnln("Invalid key size for AES: {}", key_bits); - return 1; - } - if (strlen(secret_key) != (size_t)key_bits / 8) { - warnln("Key must be exactly {} bytes long", key_bits / 8); - return 1; - } - return run(aes_cbc); - } - if (StringView(suite) == "AES_GCM") { - if (run_tests) - return aes_gcm_tests(); - - return 1; - } else { - warnln("Unknown cipher suite '{}'", suite); - return 1; - } - } - warnln("Unknown mode '{}', check out the list of modes", mode); - return 1; -} - -#define I_TEST(thing) \ - { \ - out("Testing " #thing "... "); \ - fflush(stdout); \ - gettimeofday(&start_time, nullptr); \ - } -#define PASS \ - { \ - struct timeval end_time { \ - 0, 0 \ - }; \ - gettimeofday(&end_time, nullptr); \ - time_t interval_s = end_time.tv_sec - start_time.tv_sec; \ - suseconds_t interval_us = end_time.tv_usec; \ - if (interval_us < start_time.tv_usec) { \ - interval_s -= 1; \ - interval_us += 1000000; \ - } \ - interval_us -= start_time.tv_usec; \ - outln("PASS {}s {}us", (long long)interval_s, (long long)interval_us); \ - } -#define FAIL(reason) \ - do { \ - outln("FAIL: " #reason); \ - g_some_test_failed = true; \ - } while (0) - -static ReadonlyBytes operator""_b(const char* string, size_t length) -{ - return ReadonlyBytes(string, length); -} - -// tests go after here -// please be reasonable with orders kthx -static void aes_cbc_test_name(); -static void aes_cbc_test_encrypt(); -static void aes_cbc_test_decrypt(); -static void aes_ctr_test_name(); -static void aes_ctr_test_encrypt(); -static void aes_ctr_test_decrypt(); -static void aes_gcm_test_name(); -static void aes_gcm_test_encrypt(); -static void aes_gcm_test_decrypt(); - -static void md5_test_name(); -static void md5_test_hash(); -static void md5_test_consecutive_updates(); - -static void sha1_test_name(); -static void sha1_test_hash(); - -static void sha256_test_name(); -static void sha256_test_hash(); - -static void sha384_test_name(); -static void sha384_test_hash(); - -static void sha512_test_name(); -static void sha512_test_hash(); - -static void ghash_test_name(); -static void ghash_test_process(); - -static void hmac_md5_test_name(); -static void hmac_md5_test_process(); - -static void hmac_sha256_test_name(); -static void hmac_sha256_test_process(); - -static void hmac_sha512_test_name(); -static void hmac_sha512_test_process(); - -static void hmac_sha1_test_name(); -static void hmac_sha1_test_process(); - -static void rsa_test_encrypt(); -static void rsa_test_der_parse(); -static void rsa_test_encrypt_decrypt(); -static void rsa_emsa_pss_test_create(); - -static void tls_test_client_hello(); - -static void bigint_test_fibo500(); -static void bigint_addition_edgecases(); -static void bigint_subtraction(); -static void bigint_multiplication(); -static void bigint_division(); -static void bigint_base10(); -static void bigint_import_export(); -static void bigint_bitwise(); - -static void bigint_theory_modular_inverse(); -static void bigint_theory_modular_power(); -static void bigint_theory_primality(); -static void bigint_theory_random_number(); - -static void bigint_test_signed_fibo500(); -static void bigint_signed_addition_edgecases(); -static void bigint_signed_subtraction(); -static void bigint_signed_multiplication(); -static void bigint_signed_division(); -static void bigint_signed_base10(); -static void bigint_signed_import_export(); -static void bigint_signed_bitwise(); - -static int aes_cbc_tests() -{ - aes_cbc_test_name(); - if (encrypting) { - aes_cbc_test_encrypt(); - } else { - aes_cbc_test_decrypt(); - } - - return g_some_test_failed ? 1 : 0; -} - -static void aes_cbc_test_name() -{ - I_TEST((AES CBC class name)); - Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriends"_b, 128, Crypto::Cipher::Intent::Encryption); - if (cipher.class_name() != "AES_CBC") - FAIL(Invalid class name); - else - PASS; -} - -static void aes_cbc_test_encrypt() -{ - auto test_it = [](auto& cipher, auto& result) { - auto in = "This is a test! This is another test!"_b; - auto out = cipher.create_aligned_buffer(in.size()).release_value(); - auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()).release_value(); - auto out_span = out.bytes(); - cipher.encrypt(in, out_span, iv); - if (out.size() != sizeof(result)) - FAIL(size mismatch); - else if (memcmp(out_span.data(), result, out_span.size()) != 0) { - FAIL(invalid data); - print_buffer(out_span, Crypto::Cipher::AESCipher::block_size()); - } else - PASS; - }; - { - I_TEST((AES CBC with 128 bit key | Encrypt)) - u8 result[] { - 0xb8, 0x06, 0x7c, 0xf2, 0xa9, 0x56, 0x63, 0x58, 0x2d, 0x5c, 0xa1, 0x4b, 0xc5, 0xe3, 0x08, - 0xcf, 0xb5, 0x93, 0xfb, 0x67, 0xb6, 0xf7, 0xaf, 0x45, 0x34, 0x64, 0x70, 0x9e, 0xc9, 0x1a, - 0x8b, 0xd3, 0x70, 0x45, 0xf0, 0x79, 0x65, 0xca, 0xb9, 0x03, 0x88, 0x72, 0x1c, 0xdd, 0xab, - 0x45, 0x6b, 0x1c - }; - Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriends"_b, 128, Crypto::Cipher::Intent::Encryption); - test_it(cipher, result); - } - { - I_TEST((AES CBC with 192 bit key | Encrypt)) - u8 result[] { - 0xae, 0xd2, 0x70, 0xc4, 0x9c, 0xaa, 0x83, 0x33, 0xd3, 0xd3, 0xac, 0x11, 0x65, 0x35, 0xf7, - 0x19, 0x48, 0x7c, 0x7a, 0x8a, 0x95, 0x64, 0xe7, 0xc6, 0x0a, 0xdf, 0x10, 0x06, 0xdc, 0x90, - 0x68, 0x51, 0x09, 0xd7, 0x3b, 0x48, 0x1b, 0x8a, 0xd3, 0x50, 0x09, 0xba, 0xfc, 0xde, 0x11, - 0xe0, 0x3f, 0xcb - }; - Crypto::Cipher::AESCipher::CBCMode cipher("Well Hello Friends! whf!"_b, 192, Crypto::Cipher::Intent::Encryption); - test_it(cipher, result); - } - { - I_TEST((AES CBC with 256 bit key | Encrypt)) - u8 result[] { - 0x0a, 0x44, 0x4d, 0x62, 0x9e, 0x8b, 0xd8, 0x11, 0x80, 0x48, 0x2a, 0x32, 0x53, 0x61, 0xe7, - 0x59, 0x62, 0x55, 0x9e, 0xf4, 0xe6, 0xad, 0xea, 0xc5, 0x0b, 0xf6, 0xbc, 0x6a, 0xcb, 0x9c, - 0x47, 0x9f, 0xc2, 0x21, 0xe6, 0x19, 0x62, 0xc3, 0x75, 0xca, 0xab, 0x2d, 0x18, 0xa1, 0x54, - 0xd1, 0x41, 0xe6 - }; - Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriendsWellHelloFriends"_b, 256, Crypto::Cipher::Intent::Encryption); - test_it(cipher, result); - } - { - I_TEST((AES CBC with 256 bit key | Encrypt with unsigned key)) - u8 result[] { - 0x18, 0x71, 0x80, 0x4c, 0x28, 0x07, 0x55, 0x3c, 0x05, 0x33, 0x36, 0x3f, 0x19, 0x38, 0x5c, - 0xbe, 0xf8, 0xb8, 0x0e, 0x0e, 0x66, 0x67, 0x63, 0x9c, 0xbf, 0x73, 0xcd, 0x82, 0xf9, 0xcb, - 0x9d, 0x81, 0x56, 0xc6, 0x75, 0x14, 0x8b, 0x79, 0x60, 0xb0, 0xdf, 0xaa, 0x2c, 0x2b, 0xd4, - 0xd6, 0xa0, 0x46 - }; - u8 key[] { 0x0a, 0x8c, 0x5b, 0x0d, 0x8a, 0x68, 0x43, 0xf7, 0xaf, 0xc0, 0xe3, 0x4e, 0x4b, 0x43, 0xaa, 0x28, 0x69, 0x9b, 0x6f, 0xe7, 0x24, 0x82, 0x1c, 0x71, 0x86, 0xf6, 0x2b, 0x87, 0xd6, 0x8b, 0x8f, 0xf1 }; - Crypto::Cipher::AESCipher::CBCMode cipher(ReadonlyBytes { key, sizeof(key) }, 256, Crypto::Cipher::Intent::Encryption); - test_it(cipher, result); - } - // TODO: Test non-CMS padding options -} -static void aes_cbc_test_decrypt() -{ - auto test_it = [](auto& cipher, auto& result, auto result_len) { - auto true_value = "This is a test! This is another test!"; - auto in = ByteBuffer::copy(result, result_len).release_value(); - auto out = cipher.create_aligned_buffer(in.size()).release_value(); - auto iv = ByteBuffer::create_zeroed(Crypto::Cipher::AESCipher::block_size()).release_value(); - auto out_span = out.bytes(); - cipher.decrypt(in, out_span, iv); - if (out_span.size() != strlen(true_value)) { - FAIL(size mismatch); - outln("Expected {} bytes but got {}", strlen(true_value), out_span.size()); - } else if (memcmp(out_span.data(), true_value, strlen(true_value)) != 0) { - FAIL(invalid data); - print_buffer(out_span, Crypto::Cipher::AESCipher::block_size()); - } else - PASS; - }; - { - I_TEST((AES CBC with 128 bit key | Decrypt)) - u8 result[] { - 0xb8, 0x06, 0x7c, 0xf2, 0xa9, 0x56, 0x63, 0x58, 0x2d, 0x5c, 0xa1, 0x4b, 0xc5, 0xe3, 0x08, - 0xcf, 0xb5, 0x93, 0xfb, 0x67, 0xb6, 0xf7, 0xaf, 0x45, 0x34, 0x64, 0x70, 0x9e, 0xc9, 0x1a, - 0x8b, 0xd3, 0x70, 0x45, 0xf0, 0x79, 0x65, 0xca, 0xb9, 0x03, 0x88, 0x72, 0x1c, 0xdd, 0xab, - 0x45, 0x6b, 0x1c - }; - Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriends"_b, 128, Crypto::Cipher::Intent::Decryption); - test_it(cipher, result, 48); - } - { - I_TEST((AES CBC with 192 bit key | Decrypt)) - u8 result[] { - 0xae, 0xd2, 0x70, 0xc4, 0x9c, 0xaa, 0x83, 0x33, 0xd3, 0xd3, 0xac, 0x11, 0x65, 0x35, 0xf7, - 0x19, 0x48, 0x7c, 0x7a, 0x8a, 0x95, 0x64, 0xe7, 0xc6, 0x0a, 0xdf, 0x10, 0x06, 0xdc, 0x90, - 0x68, 0x51, 0x09, 0xd7, 0x3b, 0x48, 0x1b, 0x8a, 0xd3, 0x50, 0x09, 0xba, 0xfc, 0xde, 0x11, - 0xe0, 0x3f, 0xcb - }; - Crypto::Cipher::AESCipher::CBCMode cipher("Well Hello Friends! whf!"_b, 192, Crypto::Cipher::Intent::Decryption); - test_it(cipher, result, 48); - } - { - I_TEST((AES CBC with 256 bit key | Decrypt)) - u8 result[] { - 0x0a, 0x44, 0x4d, 0x62, 0x9e, 0x8b, 0xd8, 0x11, 0x80, 0x48, 0x2a, 0x32, 0x53, 0x61, 0xe7, - 0x59, 0x62, 0x55, 0x9e, 0xf4, 0xe6, 0xad, 0xea, 0xc5, 0x0b, 0xf6, 0xbc, 0x6a, 0xcb, 0x9c, - 0x47, 0x9f, 0xc2, 0x21, 0xe6, 0x19, 0x62, 0xc3, 0x75, 0xca, 0xab, 0x2d, 0x18, 0xa1, 0x54, - 0xd1, 0x41, 0xe6 - }; - Crypto::Cipher::AESCipher::CBCMode cipher("WellHelloFriendsWellHelloFriends"_b, 256, Crypto::Cipher::Intent::Decryption); - test_it(cipher, result, 48); - } - // TODO: Test non-CMS padding options -} - -static int aes_ctr_tests() -{ - aes_ctr_test_name(); - if (encrypting) { - aes_ctr_test_encrypt(); - } else { - aes_ctr_test_decrypt(); - } - - return g_some_test_failed ? 1 : 0; -} - -static void aes_ctr_test_name() -{ - I_TEST((AES CTR class name)); - Crypto::Cipher::AESCipher::CTRMode cipher("WellHelloFriends"_b, 128, Crypto::Cipher::Intent::Encryption); - if (cipher.class_name() != "AES_CTR") - FAIL(Invalid class name); - else - PASS; -} - -#define AS_BB(x) (ReadonlyBytes { (x), sizeof((x)) / sizeof((x)[0]) }) -static void aes_ctr_test_encrypt() -{ - auto test_it = [](auto key, auto ivec, auto in, auto out_expected) { - // nonce is already included in ivec. - Crypto::Cipher::AESCipher::CTRMode cipher(key, 8 * key.size(), Crypto::Cipher::Intent::Encryption); - ByteBuffer out_actual = ByteBuffer::create_zeroed(in.size()).release_value(); - Bytes out_span = out_actual.bytes(); - cipher.encrypt(in, out_span, ivec); - if (out_expected.size() != out_actual.size()) { - FAIL(size mismatch); - outln("Expected {} bytes but got {}", out_expected.size(), out_span.size()); - print_buffer(out_span, Crypto::Cipher::AESCipher::block_size()); - } else if (memcmp(out_expected.data(), out_span.data(), out_expected.size()) != 0) { - FAIL(invalid data); - print_buffer(out_span, Crypto::Cipher::AESCipher::block_size()); - } else - PASS; - }; - // From RFC 3686, Section 6 - { - // Test Vector #1 - I_TEST((AES CTR 16 octets with 128 bit key | Encrypt)) - u8 key[] { - 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc, 0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e - }; - u8 ivec[] { - 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x73, 0x67 - }; - u8 out[] { - 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79, 0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #2 - I_TEST((AES CTR 32 octets with 128 bit key | Encrypt)) - u8 key[] { - 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7, 0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63 - }; - u8 ivec[] { - 0x00, 0x6c, 0xb6, 0xdb, 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }; - u8 out[] { - 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9, 0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88, - 0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8, 0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #3 - I_TEST((AES CTR 36 octets with 128 bit key | Encrypt)) - u8 key[] { - 0x76, 0x91, 0xbe, 0x03, 0x5e, 0x50, 0x20, 0xa8, 0xac, 0x6e, 0x61, 0x85, 0x29, 0xf9, 0xa0, 0xdc - }; - u8 ivec[] { - 0x00, 0xe0, 0x01, 0x7b, 0x27, 0x77, 0x7f, 0x3f, 0x4a, 0x17, 0x86, 0xf0, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 - }; - u8 out[] { - 0xc1, 0xcf, 0x48, 0xa8, 0x9f, 0x2f, 0xfd, 0xd9, 0xcf, 0x46, 0x52, 0xe9, 0xef, 0xdb, 0x72, 0xd7, 0x45, 0x40, 0xa4, 0x2b, 0xde, 0x6d, 0x78, 0x36, 0xd5, 0x9a, 0x5c, 0xea, 0xae, 0xf3, 0x10, 0x53, 0x25, 0xb2, 0x07, 0x2f - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #4 - I_TEST((AES CTR 16 octets with 192 bit key | Encrypt)) - u8 key[] { - 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79, 0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed, 0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15 - }; - u8 ivec[] { - 0x00, 0x00, 0x00, 0x48, 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x73, 0x67 - }; - u8 out[] { - 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8, 0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #5 - I_TEST((AES CTR 32 octets with 192 bit key | Encrypt)) - u8 key[] { - 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c, 0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c, 0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a - }; - u8 ivec[] { - 0x00, 0x96, 0xb0, 0x3b, 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }; - u8 out[] { - 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32, 0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f, 0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c, 0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #6 - I_TEST((AES CTR 36 octets with 192 bit key | Encrypt)) - u8 key[] { - 0x02, 0xbf, 0x39, 0x1e, 0xe8, 0xec, 0xb1, 0x59, 0xb9, 0x59, 0x61, 0x7b, 0x09, 0x65, 0x27, 0x9b, 0xf5, 0x9b, 0x60, 0xa7, 0x86, 0xd3, 0xe0, 0xfe - }; - u8 ivec[] { - 0x00, 0x07, 0xbd, 0xfd, 0x5c, 0xbd, 0x60, 0x27, 0x8d, 0xcc, 0x09, 0x12, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 - }; - u8 out[] { - 0x96, 0x89, 0x3f, 0xc5, 0x5e, 0x5c, 0x72, 0x2f, 0x54, 0x0b, 0x7d, 0xd1, 0xdd, 0xf7, 0xe7, 0x58, 0xd2, 0x88, 0xbc, 0x95, 0xc6, 0x91, 0x65, 0x88, 0x45, 0x36, 0xc8, 0x11, 0x66, 0x2f, 0x21, 0x88, 0xab, 0xee, 0x09, 0x35 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #7 - I_TEST((AES CTR 16 octets with 256 bit key | Encrypt)) - u8 key[] { - 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f, 0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c, 0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3, 0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04 - }; - u8 ivec[] { - 0x00, 0x00, 0x00, 0x60, 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x73, 0x67 - }; - u8 out[] { - 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7, 0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #8 - I_TEST((AES CTR 32 octets with 256 bit key | Encrypt)) - u8 key[] { - 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb, 0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86, 0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74, 0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84 - }; - u8 ivec[] { - 0x00, 0xfa, 0xac, 0x24, 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f - }; - u8 out[] { - 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c, 0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9, 0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a, 0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - { - // Test Vector #9 - I_TEST((AES CTR 36 octets with 256 bit key | Encrypt)) - u8 key[] { - 0xff, 0x7a, 0x61, 0x7c, 0xe6, 0x91, 0x48, 0xe4, 0xf1, 0x72, 0x6e, 0x2f, 0x43, 0x58, 0x1d, 0xe2, 0xaa, 0x62, 0xd9, 0xf8, 0x05, 0x53, 0x2e, 0xdf, 0xf1, 0xee, 0xd6, 0x87, 0xfb, 0x54, 0x15, 0x3d - }; - u8 ivec[] { - 0x00, 0x1c, 0xc5, 0xb7, 0x51, 0xa5, 0x1d, 0x70, 0xa1, 0xc1, 0x11, 0x48, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 - }; - u8 out[] { - 0xeb, 0x6c, 0x52, 0x82, 0x1d, 0x0b, 0xbb, 0xf7, 0xce, 0x75, 0x94, 0x46, 0x2a, 0xca, 0x4f, 0xaa, 0xb4, 0x07, 0xdf, 0x86, 0x65, 0x69, 0xfd, 0x07, 0xf4, 0x8c, 0xc0, 0xb5, 0x83, 0xd6, 0x07, 0x1f, 0x1e, 0xc0, 0xe6, 0xb8 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - // Manual test case - { - // This test checks whether counter overflow crashes. - I_TEST((AES CTR 36 octets with 256 bit key, high counter | Encrypt)) - u8 key[] { - 0xff, 0x7a, 0x61, 0x7c, 0xe6, 0x91, 0x48, 0xe4, 0xf1, 0x72, 0x6e, 0x2f, 0x43, 0x58, 0x1d, 0xe2, 0xaa, 0x62, 0xd9, 0xf8, 0x05, 0x53, 0x2e, 0xdf, 0xf1, 0xee, 0xd6, 0x87, 0xfb, 0x54, 0x15, 0x3d - }; - u8 ivec[] { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - u8 in[] { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 - }; - u8 out[] { - // Pasted from the output. The actual success condition is - // not crashing when incrementing the counter. - 0x6e, 0x8c, 0xfc, 0x59, 0x08, 0xa8, 0xc0, 0xf1, 0xe6, 0x85, 0x96, 0xe9, 0xc5, 0x40, 0xb6, 0x8b, 0xfe, 0x28, 0x72, 0xe2, 0x24, 0x11, 0x7e, 0x59, 0xef, 0xac, 0x5c, 0xe1, 0x06, 0x89, 0x09, 0xab, 0xf8, 0x90, 0x1c, 0x66 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } -} - -static void aes_ctr_test_decrypt() -{ - auto test_it = [](auto key, auto ivec, auto in, auto out_expected) { - // nonce is already included in ivec. - Crypto::Cipher::AESCipher::CTRMode cipher(key, 8 * key.size(), Crypto::Cipher::Intent::Decryption); - ByteBuffer out_actual = ByteBuffer::create_zeroed(in.size()).release_value(); - auto out_span = out_actual.bytes(); - cipher.decrypt(in, out_span, ivec); - if (out_expected.size() != out_span.size()) { - FAIL(size mismatch); - outln("Expected {} bytes but got {}", out_expected.size(), out_span.size()); - print_buffer(out_span, Crypto::Cipher::AESCipher::block_size()); - } else if (memcmp(out_expected.data(), out_span.data(), out_expected.size()) != 0) { - FAIL(invalid data); - print_buffer(out_span, Crypto::Cipher::AESCipher::block_size()); - } else - PASS; - }; - // From RFC 3686, Section 6 - { - // Test Vector #1 - I_TEST((AES CTR 16 octets with 128 bit key | Decrypt)) - u8 key[] { - 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc, 0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e - }; - u8 ivec[] { - 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 1 // See CTR.h - }; - u8 out[] { - 0x53, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x73, 0x67 - }; - u8 in[] { - 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79, 0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 - }; - test_it(AS_BB(key), AS_BB(ivec), AS_BB(in), AS_BB(out)); - } - // If encryption works, then decryption works, too. -} - -static int aes_gcm_tests() -{ - aes_gcm_test_name(); - if (encrypting) { - aes_gcm_test_encrypt(); - } else { - aes_gcm_test_decrypt(); - } - - return g_some_test_failed ? 1 : 0; -} - -static void aes_gcm_test_name() -{ - I_TEST((AES GCM class name)); - Crypto::Cipher::AESCipher::GCMMode cipher("WellHelloFriends"_b, 128, Crypto::Cipher::Intent::Encryption); - if (cipher.class_name() != "AES_GCM") - FAIL(Invalid class name); - else - PASS; -} - -static void aes_gcm_test_encrypt() -{ - { - I_TEST((AES GCM Encrypt | Empty)); - Crypto::Cipher::AESCipher::GCMMode cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 result_tag[] { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }; - Bytes out; - auto tag = ByteBuffer::create_uninitialized(16).release_value(); - cipher.encrypt({}, out, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, {}, tag); - if (memcmp(result_tag, tag.data(), tag.size()) != 0) { - FAIL(Invalid auth tag); - print_buffer(tag, -1); - } else - PASS; - } - { - I_TEST((AES GCM Encrypt | Zeros)); - Crypto::Cipher::AESCipher::GCMMode cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 result_tag[] { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }; - u8 result_ct[] { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }; - auto tag = ByteBuffer::create_uninitialized(16).release_value(); - auto out = ByteBuffer::create_uninitialized(16).release_value(); - auto out_bytes = out.bytes(); - cipher.encrypt("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, out_bytes, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, {}, tag); - if (memcmp(result_ct, out.data(), out.size()) != 0) { - FAIL(Invalid ciphertext); - print_buffer(out, -1); - } else if (memcmp(result_tag, tag.data(), tag.size()) != 0) { - FAIL(Invalid auth tag); - print_buffer(tag, -1); - } else - PASS; - } - { - I_TEST((AES GCM Encrypt | Multiple Blocks With IV)); - Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 result_tag[] { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }; - u8 result_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }; - auto tag = ByteBuffer::create_uninitialized(16).release_value(); - auto out = ByteBuffer::create_uninitialized(64).release_value(); - auto out_bytes = out.bytes(); - cipher.encrypt( - "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55"_b, - out_bytes, - "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88\x00\x00\x00\x00"_b, - {}, - tag); - if (memcmp(result_ct, out.data(), out.size()) != 0) { - FAIL(Invalid ciphertext); - print_buffer(out, -1); - } else if (memcmp(result_tag, tag.data(), tag.size()) != 0) { - FAIL(Invalid auth tag); - print_buffer(tag, -1); - } else - PASS; - } - { - I_TEST((AES GCM Encrypt | With AAD)); - Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 result_tag[] { 0x93, 0xae, 0x16, 0x97, 0x49, 0xa3, 0xbf, 0x39, 0x4f, 0x61, 0xb7, 0xc1, 0xb1, 0x2, 0x4f, 0x60 }; - u8 result_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }; - auto tag = ByteBuffer::create_uninitialized(16).release_value(); - auto out = ByteBuffer::create_uninitialized(64).release_value(); - auto out_bytes = out.bytes(); - cipher.encrypt( - "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55"_b, - out_bytes, - "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88\x00\x00\x00\x00"_b, - "\xde\xad\xbe\xef\xfa\xaf\x11\xcc"_b, - tag); - if (memcmp(result_ct, out.data(), out.size()) != 0) { - FAIL(Invalid ciphertext); - print_buffer(out, -1); - } else if (memcmp(result_tag, tag.data(), tag.size()) != 0) { - FAIL(Invalid auth tag); - print_buffer(tag, -1); - } else - PASS; - } -} - -static void aes_gcm_test_decrypt() -{ - { - I_TEST((AES GCM Decrypt | Empty)); - Crypto::Cipher::AESCipher::GCMMode cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 input_tag[] { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }; - Bytes out; - auto consistency = cipher.decrypt({}, out, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, {}, { input_tag, 16 }); - if (consistency != Crypto::VerificationConsistency::Consistent) { - FAIL(Verification reported inconsistent); - } else if (out.size() != 0) { - FAIL(Invalid plain text); - } else - PASS; - } - { - I_TEST((AES GCM Decrypt | Zeros)); - Crypto::Cipher::AESCipher::GCMMode cipher("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 input_tag[] { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }; - u8 input_ct[] { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }; - u8 result_pt[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - auto out = ByteBuffer::create_uninitialized(16).release_value(); - auto out_bytes = out.bytes(); - auto consistency = cipher.decrypt({ input_ct, 16 }, out_bytes, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"_b, {}, { input_tag, 16 }); - if (consistency != Crypto::VerificationConsistency::Consistent) { - FAIL(Verification reported inconsistent); - } else if (memcmp(result_pt, out.data(), out.size()) != 0) { - FAIL(Invalid plaintext); - print_buffer(out, -1); - } else - PASS; - } - { - I_TEST((AES GCM Decrypt | Multiple Blocks With IV)); - Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 input_tag[] { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }; - u8 input_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }; - u8 result_pt[] { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }; - auto out = ByteBuffer::create_uninitialized(64).release_value(); - auto out_bytes = out.bytes(); - - auto consistency = cipher.decrypt( - { input_ct, 64 }, - out_bytes, - "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88\x00\x00\x00\x00"_b, - {}, - { input_tag, 16 }); - if (memcmp(result_pt, out.data(), out.size()) != 0) { - FAIL(Invalid plaintext); - print_buffer(out, -1); - } else if (consistency != Crypto::VerificationConsistency::Consistent) { - FAIL(Verification reported inconsistent); - } else - PASS; - } - { - I_TEST((AES GCM Decrypt | With AAD)); - Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 input_tag[] { 0x93, 0xae, 0x16, 0x97, 0x49, 0xa3, 0xbf, 0x39, 0x4f, 0x61, 0xb7, 0xc1, 0xb1, 0x2, 0x4f, 0x60 }; - u8 input_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }; - u8 result_pt[] { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }; - auto out = ByteBuffer::create_uninitialized(64).release_value(); - auto out_bytes = out.bytes(); - auto consistency = cipher.decrypt( - { input_ct, 64 }, - out_bytes, - "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88\x00\x00\x00\x00"_b, - "\xde\xad\xbe\xef\xfa\xaf\x11\xcc"_b, - { input_tag, 16 }); - if (memcmp(result_pt, out.data(), out.size()) != 0) { - FAIL(Invalid plaintext); - print_buffer(out, -1); - } else if (consistency != Crypto::VerificationConsistency::Consistent) { - FAIL(Verification reported inconsistent); - } else - PASS; - } - { - I_TEST((AES GCM Decrypt | With AAD - Invalid Tag)); - Crypto::Cipher::AESCipher::GCMMode cipher("\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"_b, 128, Crypto::Cipher::Intent::Encryption); - u8 input_tag[] { 0x94, 0xae, 0x16, 0x97, 0x49, 0xa3, 0xbf, 0x39, 0x4f, 0x61, 0xb7, 0xc1, 0xb1, 0x2, 0x4f, 0x60 }; - u8 input_ct[] { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }; - auto out = ByteBuffer::create_uninitialized(64).release_value(); - auto out_bytes = out.bytes(); - auto consistency = cipher.decrypt( - { input_ct, 64 }, - out_bytes, - "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88\x00\x00\x00\x00"_b, - "\xde\xad\xbe\xef\xfa\xaf\x11\xcc"_b, - { input_tag, 16 }); - - if (consistency != Crypto::VerificationConsistency::Inconsistent) - FAIL(Verification reported consistent); - else - PASS; - } -} - -static int md5_tests() -{ - md5_test_name(); - md5_test_hash(); - md5_test_consecutive_updates(); - return g_some_test_failed ? 1 : 0; -} - -static void md5_test_name() -{ - I_TEST((MD5 class name)); - Crypto::Hash::MD5 md5; - if (md5.class_name() != "MD5") - FAIL(Invalid class name); - else - PASS; -} - -static void md5_test_hash() -{ - { - I_TEST((MD5 Hashing | "Well hello friends")); - u8 result[] { - 0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c - }; - auto digest = Crypto::Hash::MD5::hash("Well hello friends"); - - if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::MD5::digest_size() }, -1); - } else { - PASS; - } - } - // RFC tests - { - I_TEST((MD5 Hashing | "")); - u8 result[] { - 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e - }; - auto digest = Crypto::Hash::MD5::hash(""); - - if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::MD5::digest_size() }, -1); - } else { - PASS; - } - } - { - I_TEST((MD5 Hashing | "a")); - u8 result[] { - 0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 - }; - auto digest = Crypto::Hash::MD5::hash("a"); - - if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::MD5::digest_size() }, -1); - } else { - PASS; - } - } - { - I_TEST((MD5 Hashing | "abcdefghijklmnopqrstuvwxyz")); - u8 result[] { - 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b - }; - auto digest = Crypto::Hash::MD5::hash("abcdefghijklmnopqrstuvwxyz"); - - if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::MD5::digest_size() }, -1); - } else { - PASS; - } - } - { - I_TEST((MD5 Hashing | Long Sequence)); - u8 result[] { - 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a - }; - auto digest = Crypto::Hash::MD5::hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); - - if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::MD5::digest_size() }, -1); - } else { - PASS; - } - } -} - -static void md5_test_consecutive_updates() -{ - { - I_TEST((MD5 Hashing | Multiple Updates)); - u8 result[] { - 0xaf, 0x04, 0x3a, 0x08, 0x94, 0x38, 0x6e, 0x7f, 0xbf, 0x73, 0xe4, 0xaa, 0xf0, 0x8e, 0xee, 0x4c - }; - Crypto::Hash::MD5 md5; - - md5.update("Well"); - md5.update(" hello "); - md5.update("friends"); - auto digest = md5.digest(); - - if (memcmp(result, digest.data, Crypto::Hash::MD5::digest_size()) != 0) - FAIL(Invalid hash); - else - PASS; - } - { - I_TEST((MD5 Hashing | Reuse)); - Crypto::Hash::MD5 md5; - - md5.update("Well"); - md5.update(" hello "); - md5.update("friends"); - auto digest0 = md5.digest(); - - md5.update("Well"); - md5.update(" hello "); - md5.update("friends"); - auto digest1 = md5.digest(); - - if (memcmp(digest0.data, digest1.data, Crypto::Hash::MD5::digest_size()) != 0) - FAIL(Cannot reuse); - else - PASS; - } -} - -static int hmac_md5_tests() -{ - hmac_md5_test_name(); - hmac_md5_test_process(); - return g_some_test_failed ? 1 : 0; -} - -static int hmac_sha256_tests() -{ - hmac_sha256_test_name(); - hmac_sha256_test_process(); - return g_some_test_failed ? 1 : 0; -} - -static int hmac_sha512_tests() -{ - hmac_sha512_test_name(); - hmac_sha512_test_process(); - return g_some_test_failed ? 1 : 0; -} - -static int hmac_sha1_tests() -{ - hmac_sha1_test_name(); - hmac_sha1_test_process(); - return g_some_test_failed ? 1 : 0; -} - -static void hmac_md5_test_name() -{ - I_TEST((HMAC - MD5 | Class name)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - if (hmac.class_name() != "HMAC-MD5") - FAIL(Invalid class name); - else - PASS; -} - -static void hmac_md5_test_process() -{ - { - I_TEST((HMAC - MD5 | Basic)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - u8 result[] { - 0x3b, 0x5b, 0xde, 0x30, 0x3a, 0x54, 0x7b, 0xbb, 0x09, 0xfe, 0x78, 0x89, 0xbc, 0x9f, 0x22, 0xa3 - }; - auto mac = hmac.process("Some bogus data"); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } - { - I_TEST((HMAC - MD5 | Reuse)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - - auto mac_0 = hmac.process("Some bogus data"); - auto mac_1 = hmac.process("Some bogus data"); - - if (memcmp(mac_0.data, mac_1.data, hmac.digest_size()) != 0) { - FAIL(Cannot reuse); - } else - PASS; - } -} - -static int ghash_tests() -{ - ghash_test_name(); - ghash_test_process(); - return g_some_test_failed ? 1 : 0; -} - -static void ghash_test_name() -{ - I_TEST((GHash class name)); - Crypto::Authentication::GHash ghash("WellHelloFriends"); - if (ghash.class_name() != "GHash") - FAIL(Invalid class name); - else - PASS; -} - -static void hmac_sha1_test_name() -{ - I_TEST((HMAC - SHA1 | Class name)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - if (hmac.class_name() != "HMAC-SHA1") - FAIL(Invalid class name); - else - PASS; -} - -static void hmac_sha1_test_process() -{ - { - I_TEST((HMAC - SHA1 | Basic)); - u8 key[] { 0xc8, 0x52, 0xe5, 0x4a, 0x2c, 0x03, 0x2b, 0xc9, 0x63, 0xd3, 0xc2, 0x79, 0x0f, 0x76, 0x43, 0xef, 0x36, 0xc3, 0x7a, 0xca }; - Crypto::Authentication::HMAC hmac(ReadonlyBytes { key, sizeof(key) }); - u8 result[] { - 0x2c, 0x57, 0x32, 0x61, 0x3b, 0xa7, 0x84, 0x87, 0x0e, 0x4f, 0x42, 0x07, 0x2f, 0xf0, 0xe7, 0x41, 0xd7, 0x15, 0xf4, 0x56 - }; - u8 value[] { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0c, 0xa1, 0x91, 0x1a, 0x20, 0x59, 0xb5, 0x45, 0xa9, 0xb4, 0xad, 0x75, 0x3e - }; - auto mac = hmac.process(value, 29); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } - { - I_TEST((HMAC - SHA1 | Reuse)); - u8 key[] { 0xc8, 0x52, 0xe5, 0x4a, 0x2c, 0x03, 0x2b, 0xc9, 0x63, 0xd3, 0xc2, 0x79, 0x0f, 0x76, 0x43, 0xef, 0x36, 0xc3, 0x7a, 0xca }; - Crypto::Authentication::HMAC hmac(ReadonlyBytes { key, sizeof(key) }); - u8 result[] { - 0x2c, 0x57, 0x32, 0x61, 0x3b, 0xa7, 0x84, 0x87, 0x0e, 0x4f, 0x42, 0x07, 0x2f, 0xf0, 0xe7, 0x41, 0xd7, 0x15, 0xf4, 0x56 - }; - u8 value[] { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x03, 0x03, 0x00, 0x10, 0x14, 0x00, 0x00, 0x0c, 0xa1, 0x91, 0x1a, 0x20, 0x59, 0xb5, 0x45, 0xa9, 0xb4, 0xad, 0x75, 0x3e - }; - hmac.update(value, 8); - hmac.update(value + 8, 5); - hmac.update(value + 13, 16); - auto mac = hmac.digest(); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } -} - -static void ghash_test_process() -{ - { - I_TEST((GHash | Galois Field Multiply)); - u32 x[4] { 0x42831ec2, 0x21777424, 0x4b7221b7, 0x84d0d49c }, - y[4] { 0xb83b5337, 0x08bf535d, 0x0aa6e529, 0x80d53b78 }, z[4] { 0, 0, 0, 0 }; - static constexpr u32 result[4] { 0x59ed3f2b, 0xb1a0aaa0, 0x7c9f56c6, 0xa504647b }; - - Crypto::Authentication::galois_multiply(z, x, y); - if (memcmp(result, z, 4 * sizeof(u32)) != 0) { - FAIL(Invalid multiply value); - print_buffer({ z, 4 * sizeof(u32) }, -1); - print_buffer({ result, 4 * sizeof(u32) }, -1); - } else - PASS; - } - { - I_TEST((GHash | Galois Field Multiply #2)); - u32 x[4] { 59300558, 1622582162, 4079534777, 1907555960 }, - y[4] { 1726565332, 4018809915, 2286746201, 3392416558 }, z[4]; - constexpr static u32 result[4] { 1580123974, 2440061576, 746958952, 1398005431 }; - - Crypto::Authentication::galois_multiply(z, x, y); - if (memcmp(result, z, 4 * sizeof(u32)) != 0) { - FAIL(Invalid multiply value); - print_buffer({ z, 4 * sizeof(u32) }, -1); - print_buffer({ result, 4 * sizeof(u32) }, -1); - } else - PASS; - } - // TODO: Add some GHash tests? - // Kinda hard, as there are no vectors and existing tools don't have an interface to it. -} - -static int sha1_tests() -{ - sha1_test_name(); - sha1_test_hash(); - return g_some_test_failed ? 1 : 0; -} - -static void sha1_test_name() -{ - I_TEST((SHA1 class name)); - Crypto::Hash::SHA1 sha; - if (sha.class_name() != "SHA1") { - FAIL(Invalid class name); - outln("{}", sha.class_name()); - } else - PASS; -} - -static void sha1_test_hash() -{ - { - I_TEST((SHA256 Hashing | "")); - u8 result[] { - 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 - }; - auto digest = Crypto::Hash::SHA1::hash(""); - if (memcmp(result, digest.data, Crypto::Hash::SHA1::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA1::digest_size() }, -1); - } else - PASS; - } - { - I_TEST((SHA256 Hashing | Long String)); - u8 result[] { - 0x12, 0x15, 0x1f, 0xb1, 0x04, 0x44, 0x93, 0xcc, 0xed, 0x54, 0xa6, 0xb8, 0x7e, 0x93, 0x37, 0x7b, 0xb2, 0x13, 0x39, 0xdb - }; - auto digest = Crypto::Hash::SHA1::hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - if (memcmp(result, digest.data, Crypto::Hash::SHA1::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA1::digest_size() }, -1); - } else - PASS; - } - { - I_TEST((SHA256 Hashing | Successive Updates)); - u8 result[] { - 0xd6, 0x6e, 0xce, 0xd1, 0xf4, 0x08, 0xc6, 0xd8, 0x35, 0xab, 0xf0, 0xc9, 0x05, 0x26, 0xa4, 0xb2, 0xb8, 0xa3, 0x7c, 0xd3 - }; - auto hasher = Crypto::Hash::SHA1 {}; - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaaaaaaaa"); - hasher.update("aaaaaaaaa"); - auto digest = hasher.digest(); - if (memcmp(result, digest.data, Crypto::Hash::SHA1::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA1::digest_size() }, -1); - } else - PASS; - } -} - -static int sha256_tests() -{ - sha256_test_name(); - sha256_test_hash(); - return g_some_test_failed ? 1 : 0; -} - -static void sha256_test_name() -{ - I_TEST((SHA256 class name)); - Crypto::Hash::SHA256 sha; - if (sha.class_name() != "SHA256") { - FAIL(Invalid class name); - outln("{}", sha.class_name()); - } else - PASS; -} - -static void sha256_test_hash() -{ - { - I_TEST((SHA256 Hashing | "Well hello friends")); - u8 result[] { - 0x9a, 0xcd, 0x50, 0xf9, 0xa2, 0xaf, 0x37, 0xe4, 0x71, 0xf7, 0x61, 0xc3, 0xfe, 0x7b, 0x8d, 0xea, 0x56, 0x17, 0xe5, 0x1d, 0xac, 0x80, 0x2f, 0xe6, 0xc1, 0x77, 0xb7, 0x4a, 0xbf, 0x0a, 0xbb, 0x5a - }; - auto digest = Crypto::Hash::SHA256::hash("Well hello friends"); - if (memcmp(result, digest.data, Crypto::Hash::SHA256::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA256::digest_size() }, -1); - } else - PASS; - } - { - I_TEST((SHA256 Hashing | "")); - u8 result[] { - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 - }; - auto digest = Crypto::Hash::SHA256::hash(""); - if (memcmp(result, digest.data, Crypto::Hash::SHA256::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA256::digest_size() }, -1); - } else - PASS; - } -} - -static void hmac_sha256_test_name() -{ - I_TEST((HMAC - SHA256 | Class name)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - if (hmac.class_name() != "HMAC-SHA256") - FAIL(Invalid class name); - else - PASS; -} - -static void hmac_sha256_test_process() -{ - { - I_TEST((HMAC - SHA256 | Basic)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - u8 result[] { - 0x1a, 0xf2, 0x20, 0x62, 0xde, 0x3b, 0x84, 0x65, 0xc1, 0x25, 0x23, 0x99, 0x76, 0x15, 0x1b, 0xec, 0x15, 0x21, 0x82, 0x1f, 0x23, 0xca, 0x11, 0x66, 0xdd, 0x8c, 0x6e, 0xf1, 0x81, 0x3b, 0x7f, 0x1b - }; - auto mac = hmac.process("Some bogus data"); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } - { - I_TEST((HMAC - SHA256 | DataSize > FinalBlockDataSize)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - u8 result[] = { - 0x9b, 0xa3, 0x9e, 0xf3, 0xb4, 0x30, 0x5f, 0x6f, 0x67, 0xd0, 0xa8, 0xb0, 0xf0, 0xcb, 0x12, 0xf5, 0x85, 0xe2, 0x19, 0xba, 0x0c, 0x8b, 0xe5, 0x43, 0xf0, 0x93, 0x39, 0xa8, 0xa3, 0x07, 0xf1, 0x95 - }; - auto mac = hmac.process("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } - { - I_TEST((HMAC - SHA256 | DataSize == BlockSize)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - u8 result[] = { - 0x1d, 0x90, 0xce, 0x68, 0x45, 0x0b, 0xba, 0xd6, 0xbe, 0x1c, 0xb2, 0x3a, 0xea, 0x7f, 0xac, 0x4b, 0x68, 0x08, 0xa4, 0x77, 0x81, 0x2a, 0xad, 0x5d, 0x05, 0xe2, 0x15, 0xe8, 0xf4, 0xcb, 0x06, 0xaf - }; - auto mac = hmac.process("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } - { - I_TEST((HMAC - SHA256 | Reuse)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - - auto mac_0 = hmac.process("Some bogus data"); - auto mac_1 = hmac.process("Some bogus data"); - - if (memcmp(mac_0.data, mac_1.data, hmac.digest_size()) != 0) { - FAIL(Cannot reuse); - } else - PASS; - } -} - -static int sha384_tests() -{ - sha384_test_name(); - sha384_test_hash(); - return g_some_test_failed ? 1 : 0; -} - -static void sha384_test_name() -{ - I_TEST((SHA384 class name)); - Crypto::Hash::SHA384 sha; - if (sha.class_name() != "SHA384") { - FAIL(Invalid class name); - outln("{}", sha.class_name()); - } else - PASS; -} - -static void sha384_test_hash() -{ - { - I_TEST((SHA384 Hashing | "Well hello friends")); - u8 result[] { - 0x2f, 0x01, 0x8e, 0x9a, 0x4f, 0xd1, 0x36, 0xb9, 0x0f, 0xcc, 0x21, 0xde, 0x1a, 0xd4, 0x49, 0x51, 0x57, 0x82, 0x86, 0x84, 0x54, 0x09, 0x82, 0x7b, 0x54, 0x56, 0x93, 0xac, 0x2c, 0x46, 0x0c, 0x1f, 0x5e, 0xec, 0xe0, 0xf7, 0x8b, 0x0b, 0x84, 0x27, 0xc8, 0xb8, 0xbe, 0x49, 0xce, 0x8f, 0x1c, 0xff - }; - auto digest = Crypto::Hash::SHA384::hash("Well hello friends"); - if (memcmp(result, digest.data, Crypto::Hash::SHA384::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA384::digest_size() }, -1); - } else - PASS; - } - { - I_TEST((SHA384 Hashing | "")); - u8 result[] { - 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b - }; - auto digest = Crypto::Hash::SHA384::hash(""); - if (memcmp(result, digest.data, Crypto::Hash::SHA384::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA384::digest_size() }, -1); - } else - PASS; - } -} - -static int sha512_tests() -{ - sha512_test_name(); - sha512_test_hash(); - return g_some_test_failed ? 1 : 0; -} - -static void sha512_test_name() -{ - I_TEST((SHA512 class name)); - Crypto::Hash::SHA512 sha; - if (sha.class_name() != "SHA512") { - FAIL(Invalid class name); - outln("{}", sha.class_name()); - } else - PASS; -} - -static void sha512_test_hash() -{ - { - I_TEST((SHA512 Hashing | "Well hello friends")); - u8 result[] { - 0x00, 0xfe, 0x68, 0x09, 0x71, 0x0e, 0xcb, 0x2b, 0xe9, 0x58, 0x00, 0x13, 0x69, 0x6a, 0x9e, 0x9e, 0xbd, 0x09, 0x1b, 0xfe, 0x14, 0xc9, 0x13, 0x82, 0xc7, 0x40, 0x34, 0xfe, 0xca, 0xe6, 0x87, 0xcb, 0x26, 0x36, 0x92, 0xe6, 0x34, 0x94, 0x3a, 0x11, 0xe5, 0xbb, 0xb5, 0xeb, 0x8e, 0x70, 0xef, 0x64, 0xca, 0xf7, 0x21, 0xb1, 0xde, 0xf2, 0x34, 0x85, 0x6f, 0xa8, 0x56, 0xd8, 0x23, 0xa1, 0x3b, 0x29 - }; - auto digest = Crypto::Hash::SHA512::hash("Well hello friends"); - if (memcmp(result, digest.data, Crypto::Hash::SHA512::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA512::digest_size() }, -1); - } else - PASS; - } - { - I_TEST((SHA512 Hashing | "")); - u8 result[] { - 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e - }; - auto digest = Crypto::Hash::SHA512::hash(""); - if (memcmp(result, digest.data, Crypto::Hash::SHA512::digest_size()) != 0) { - FAIL(Invalid hash); - print_buffer({ digest.data, Crypto::Hash::SHA512::digest_size() }, -1); - } else - PASS; - } -} - -static void hmac_sha512_test_name() -{ - I_TEST((HMAC - SHA512 | Class name)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - if (hmac.class_name() != "HMAC-SHA512") - FAIL(Invalid class name); - else - PASS; -} - -static void hmac_sha512_test_process() -{ - { - I_TEST((HMAC - SHA512 | Basic)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - u8 result[] { - 0xeb, 0xa8, 0x34, 0x11, 0xfd, 0x5b, 0x46, 0x5b, 0xef, 0xbb, 0x67, 0x5e, 0x7d, 0xc2, 0x7c, 0x2c, 0x6b, 0xe1, 0xcf, 0xe6, 0xc7, 0xe4, 0x7d, 0xeb, 0xca, 0x97, 0xb7, 0x4c, 0xd3, 0x4d, 0x6f, 0x08, 0x9f, 0x0d, 0x3a, 0xf1, 0xcb, 0x00, 0x79, 0x78, 0x2f, 0x05, 0x8e, 0xeb, 0x94, 0x48, 0x0d, 0x50, 0x64, 0x3b, 0xca, 0x70, 0xe2, 0x69, 0x38, 0x4f, 0xe4, 0xb0, 0x49, 0x0f, 0xc5, 0x4c, 0x7a, 0xa7 - }; - auto mac = hmac.process("Some bogus data"); - if (memcmp(result, mac.data, hmac.digest_size()) != 0) { - FAIL(Invalid mac); - print_buffer({ mac.data, hmac.digest_size() }, -1); - } else - PASS; - } - { - I_TEST((HMAC - SHA512 | Reuse)); - Crypto::Authentication::HMAC hmac("Well Hello Friends"); - - auto mac_0 = hmac.process("Some bogus data"); - auto mac_1 = hmac.process("Some bogus data"); - - if (memcmp(mac_0.data, mac_1.data, hmac.digest_size()) != 0) { - FAIL(Cannot reuse); - } else - PASS; - } -} - -static int rsa_tests() -{ - rsa_test_encrypt(); - rsa_test_der_parse(); - rsa_test_encrypt_decrypt(); - rsa_emsa_pss_test_create(); - return g_some_test_failed ? 1 : 0; -} - -static void rsa_test_encrypt() -{ - { - I_TEST((RSA RAW | Encryption)); - ReadonlyBytes data { "hellohellohellohellohellohellohellohellohellohellohellohello123-"_b }; - u8 result[] { 0x6f, 0x7b, 0xe2, 0xd3, 0x95, 0xf8, 0x8d, 0x87, 0x6d, 0x10, 0x5e, 0xc3, 0xcd, 0xf7, 0xbb, 0xa6, 0x62, 0x8e, 0x45, 0xa0, 0xf1, 0xe5, 0x0f, 0xdf, 0x69, 0xcb, 0xb6, 0xd5, 0x42, 0x06, 0x7d, 0x72, 0xa9, 0x5e, 0xae, 0xbf, 0xbf, 0x0f, 0xe0, 0xeb, 0x31, 0x31, 0xca, 0x8a, 0x81, 0x1e, 0xb9, 0xec, 0x6d, 0xcc, 0xb8, 0xa4, 0xac, 0xa3, 0x31, 0x05, 0xa9, 0xac, 0xc9, 0xd3, 0xe6, 0x2a, 0x18, 0xfe }; - Crypto::PK::RSA rsa( - "8126832723025844890518845777858816391166654950553329127845898924164623511718747856014227624997335860970996746552094406240834082304784428582653994490504519"_bigint, - "4234603516465654167360850580101327813936403862038934287300450163438938741499875303761385527882335478349599685406941909381269804396099893549838642251053393"_bigint, - "65537"_bigint); - u8 buffer[rsa.output_size()]; - auto buf = Bytes { buffer, sizeof(buffer) }; - rsa.encrypt(data, buf); - if (memcmp(result, buf.data(), buf.size())) { - FAIL(Invalid encryption result); - print_buffer(buf, 16); - } else { - PASS; - } - } - { - I_TEST((RSA PKCS #1 1.5 | Encryption)); - ReadonlyBytes data { "hellohellohellohellohellohellohellohellohello123-"_b }; - Crypto::PK::RSA_PKCS1_EME rsa( - "8126832723025844890518845777858816391166654950553329127845898924164623511718747856014227624997335860970996746552094406240834082304784428582653994490504519"_bigint, - "4234603516465654167360850580101327813936403862038934287300450163438938741499875303761385527882335478349599685406941909381269804396099893549838642251053393"_bigint, - "65537"_bigint); - u8 buffer[rsa.output_size()]; - auto buf = Bytes { buffer, sizeof(buffer) }; - rsa.encrypt(data, buf); - rsa.decrypt(buf, buf); - - if (memcmp(buf.data(), "hellohellohellohellohellohellohellohellohello123-", 49)) - FAIL(Invalid encryption); - else { - dbgln("out size {} values {}", buf.size(), StringView { (char*)buf.data(), buf.size() }); - - PASS; - } - } -} - -static void rsa_emsa_pss_test_create() -{ - { - // This is a template validity test - I_TEST((RSA EMSA_PSS | Construction)); - Crypto::PK::RSA rsa; - Crypto::PK::RSA_EMSA_PSS rsa_esma_pss(rsa); - PASS; - } -} - -static void rsa_test_der_parse() -{ - { - I_TEST((RSA | ASN1 PKCS1 DER / PEM encoded Key import)); - auto privkey = R"(-----BEGIN RSA PRIVATE KEY----- -MIIBOgIBAAJBAJsrIYHxs1YL9tpfodaWs1lJoMdF4kgFisUFSj6nvBhJUlmBh607AlgTaX0E -DGPYycXYGZ2n6rqmms5lpDXBpUcCAwEAAQJAUNpPkmtEHDENxsoQBUXvXDYeXdePSiIBJhpU -joNOYoR5R9z5oX2cpcyykQ58FC2vKKg+x8N6xczG7qO95tw5UQIhAN354CP/FA+uTeJ6KJ+i -zCBCl58CjNCzO0s5HTc56el5AiEAsvPKXo5/9gS/S4UzDRP6abq7GreixTfjR8LXidk3FL8C -IQCTjYI861Y+hjMnlORkGSdvWlTHUj6gjEOh4TlWeJzQoQIgAxMZOQKtxCZUuxFwzRq4xLRG -nrDlBQpuxz7bwSyQO7UCIHrYMnDohgNbwtA5ZpW3H1cKKQQvueWm6sxW9P5sUrZ3 ------END RSA PRIVATE KEY-----)"; - - Crypto::PK::RSA rsa(privkey); - if (rsa.public_key().public_exponent() == 65537) { - if (rsa.private_key().private_exponent() == "4234603516465654167360850580101327813936403862038934287300450163438938741499875303761385527882335478349599685406941909381269804396099893549838642251053393"_bigint) { - PASS; - } else - FAIL(Invalid private exponent); - } else { - FAIL(Invalid public exponent); - } - } - - { - I_TEST((RSA | ASN1 PKCS8 DER / PEM encoded Key import)); - auto privkey = R"(-----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC7ZBYaG9+CcJP7 -WVFJRI/uw3hljc7WpzeYs8MN82/g9CG1gnEF3P3ZSBdWVr8gnbh05EsSGHKghIce -CB7DNrM5Ab0ru04CuODdPx56xCj+4MmzTc/aq79ntmOt131NGHgq9yVwfJqnSpyl -OoVw7j/Wg4ciwPDQaeLmD1BsE/W9UsF1km7DWasBpW5br82DpudKgJq2Ixf52+rY -TCkMgyWcetx4MfXll4y5ZVtJXCnHJfkCS64EaCqXmClP4ovOuHH4khJ3rW9j4yuL -e5ck3PSXOrtOTR43HZkCXzseCkbW7qKSmk/9ZreImOzOgu8vvw7ewLAQR9qYVS6X -PXY8IilDAgMBAAECggEBAIV3ld5mt90Z/exqA2Fh+fofMyNxyz5Lv2d9sZHAL5FT -kKbND18TtaIKnMSb6Gl8rKJk76slyo7Vlb8oHXEBBsm1mV0KfVenAlHS4QyjpmdT -B5Yz97VR2nQuDfUFpHNC2GQRv5LMzQIWPFfaxKxYpRNOfvOb5Gks4bTmd2tjFAYR -MCbHgPw1liKA9dYKk4NB0301EY05e4Zz8RjqYHkkmOPD7DnjFbHqcFUjVKK5E3vD -WjxNXUbiSudCCN7WLEOyeHZNd+l6kSAVxZuCAp0G3Da5ndXgIStcy4hYi/fL3XQQ -bNpxjfhsjlD3tdHNr3NNYDAqxcxpsyO1NCpCIW3ZVrECgYEA7l6gTZ3e9AiSNlMd -2O2vNnbQ6UZfsEfu2y7HmpCuNJkFkAnM/1h72Krejnn31rRuR6uCFn4YgQUN9Eq0 -E1PJCtTay2ucZw5rqtkewT9QzXvVD9eiGM+MF89UzSCC+dOW0/odkD+xP2evnPvG -PbXztnuERC1pi0YWLj1YcsfsEX0CgYEAyUA2UtYjnvCcteIy+rURT0aoZ9tDMrG+ -Es42EURVv1sduVdUst5R+bXx1aDzpCkcdni3TyxeosvTGAZngI3O8ghh1GV7NPZR -nkiPXjMnhL0Zf+X9gCA6TFANfPuWhMSGijYsCd46diKGDReGYUnmcN9XopeG1h6i -3JiOuVPAIb8CgYBmIcUtfGb6yHFdNV+kgrJ/84ivaqe1MBz3bKO5ZiQ+BRKNFKXx -AkiOHSgeg8PdCpH1w1aJrJ1zKmdANIHThiKtsWXNot3wig03tq+mvSox4Mz5bLrX -RpYP3ZXIDhYQVMhbKt9f3upi8FoeOQJHjp5Nob6aN5rxQaZfSYmMJHzRQQKBgQCO -ALwUGTtLNBYvlKtKEadkG8RKfAFfbOFkXZLy/hfPDRjdJY0DJTIMk+BPT+F6rPOD -eMxHllQ0ZMPPiP1RTT5/s4BsISsdhMy0dhiLbGbvF4s9nugPly3rmPTbgp6DkjQo -o+7RC7iOkO+rnzTXwxBSBpXMiUTAIx/hrdfPVxQT+wKBgCh7N3OLIOH6EWcW1fif -UoENh8rkt/kzm89G1JLwBhuBIBPXUEZt2dS/xSUempqVqFGONpP87gvqxkMTtgCA -73KXn/cxHWM2kmXyHA3kQlOYw6WHjpldQAxLE+TRHXO2JUtZ09Mu4rVXX7lmwbTm -l3vmuDEF3/Bo1C1HTg0xRV/l ------END PRIVATE KEY-----)"; - - Crypto::PK::RSA rsa(privkey); - if (rsa.public_key().public_exponent() == 65537) { - if (rsa.private_key().private_exponent() == "16848664331299797559656678180469464902267415922431923391961407795209879741791261105581093539484181644099608161661780611501562625272630894063592208758992911105496755004417051031019663332258403844985328863382168329621318366311519850803972480500782200178279692319955495383119697563295214236936264406600739633470565823022975212999060908747002623721589308539473108154612454595201561671949550531384574873324370774408913092560971930541734744950937900805812300970883306404011323308000168926094053141613790857814489531436452649384151085451448183385611208320292948291211969430321231180227006521681776197974694030147965578466993"_bigint) { - PASS; - } else - FAIL(Invalid private exponent); - } else { - FAIL(Invalid public exponent); - } - } -} - -static void rsa_test_encrypt_decrypt() -{ - I_TEST((RSA | Encrypt)); - dbgln(" creating rsa object"); - Crypto::PK::RSA rsa( - "9527497237087650398000977129550904920919162360737979403539302312977329868395261515707123424679295515888026193056908173564681660256268221509339074678416049"_bigint, - "39542231845947188736992321577701849924317746648774438832456325878966594812143638244746284968851807975097653255909707366086606867657273809465195392910913"_bigint, - "65537"_bigint); - - dbgln("Output size: {}", rsa.output_size()); - - u8 enc_buffer[rsa.output_size()]; - u8 dec_buffer[rsa.output_size()]; - - auto enc = Bytes { enc_buffer, rsa.output_size() }; - auto dec = Bytes { dec_buffer, rsa.output_size() }; - - enc.overwrite(0, "WellHelloFriendsWellHelloFriendsWellHelloFriendsWellHelloFriends", 64); - - rsa.encrypt(enc, dec); - rsa.decrypt(dec, enc); - - dbgln("enc size {} dec size {}", enc.size(), dec.size()); - - if (memcmp(enc.data(), "WellHelloFriendsWellHelloFriendsWellHelloFriendsWellHelloFriends", 64) != 0) { - FAIL(Could not encrypt then decrypt); - } else { - PASS; - } -} - -static int tls_tests() -{ - tls_test_client_hello(); - return g_some_test_failed ? 1 : 0; -} - -static void tls_test_client_hello() -{ - I_TEST((TLS | Connect and Data Transfer)); - Core::EventLoop loop; - RefPtr tls = TLS::TLSv12::construct(nullptr); - tls->set_root_certificates(s_root_ca_certificates); - bool sent_request = false; - ByteBuffer contents; - tls->set_on_tls_ready_to_write([&](TLS::TLSv12& tls) { - if (sent_request) - return; - sent_request = true; - Core::deferred_invoke([&tls] { tls.set_on_tls_ready_to_write(nullptr); }); - if (!tls.write("GET / HTTP/1.1\r\nHost: "_b)) { - FAIL(write(0) failed); - loop.quit(0); - } - auto* the_server = server ?: DEFAULT_SERVER; - if (!tls.write(StringView(the_server).bytes())) { - FAIL(write(1) failed); - loop.quit(0); - } - if (!tls.write("\r\nConnection : close\r\n\r\n"_b)) { - FAIL(write(2) failed); - loop.quit(0); - } - }); - tls->on_tls_ready_to_read = [&](TLS::TLSv12& tls) { - auto data = tls.read(); - if (!data.has_value()) { - FAIL(No data received); - loop.quit(1); - } else { - // print_buffer(data.value(), 16); - if (contents.try_append(data.value().data(), data.value().size()).is_error()) { - FAIL(Allocation failed); - loop.quit(1); - } - } - }; - tls->on_tls_finished = [&] { - PASS; - loop.quit(0); - }; - tls->on_tls_error = [&](TLS::AlertDescription) { - FAIL(Connection failure); - loop.quit(1); - }; - if (!tls->connect(server ?: DEFAULT_SERVER, port)) { - FAIL(connect() failed); - return; - } - loop.exec(); -} - -static int adler32_tests() -{ - auto do_test = [](ReadonlyBytes input, u32 expected_result) { - I_TEST((CRC32)); - - auto pass = Crypto::Checksum::Adler32(input).digest() == expected_result; - - if (pass) { - PASS; - } else { - FAIL(Incorrect Result); - } - }; - - do_test(String("").bytes(), 0x1); - do_test(String("a").bytes(), 0x00620062); - do_test(String("abc").bytes(), 0x024d0127); - do_test(String("message digest").bytes(), 0x29750586); - do_test(String("abcdefghijklmnopqrstuvwxyz").bytes(), 0x90860b20); - - return g_some_test_failed ? 1 : 0; -} - -static int crc32_tests() -{ - auto do_test = [](ReadonlyBytes input, u32 expected_result) { - I_TEST((Adler32)); - - auto pass = Crypto::Checksum::CRC32(input).digest() == expected_result; - - if (pass) { - PASS; - } else { - FAIL(Incorrect Result); - } - }; - - do_test(String("").bytes(), 0x0); - do_test(String("The quick brown fox jumps over the lazy dog").bytes(), 0x414FA339); - do_test(String("various CRC algorithms input data").bytes(), 0x9BD366AE); - - return g_some_test_failed ? 1 : 0; -} - -static int bigint_tests() -{ - bigint_test_fibo500(); - bigint_addition_edgecases(); - bigint_subtraction(); - bigint_multiplication(); - bigint_division(); - bigint_base10(); - bigint_import_export(); - bigint_bitwise(); - - bigint_theory_modular_inverse(); - bigint_theory_modular_power(); - bigint_theory_primality(); - bigint_theory_random_number(); - - bigint_test_signed_fibo500(); - bigint_signed_addition_edgecases(); - bigint_signed_subtraction(); - bigint_signed_multiplication(); - bigint_signed_division(); - bigint_signed_base10(); - bigint_signed_import_export(); - bigint_signed_bitwise(); - - return g_some_test_failed ? 1 : 0; -} - -static Crypto::UnsignedBigInteger bigint_fibonacci(size_t n) -{ - Crypto::UnsignedBigInteger num1(0); - Crypto::UnsignedBigInteger num2(1); - for (size_t i = 0; i < n; ++i) { - Crypto::UnsignedBigInteger t = num1.plus(num2); - num2 = num1; - num1 = t; - } - return num1; -} - -static Crypto::SignedBigInteger bigint_signed_fibonacci(size_t n) -{ - Crypto::SignedBigInteger num1(0); - Crypto::SignedBigInteger num2(1); - for (size_t i = 0; i < n; ++i) { - Crypto::SignedBigInteger t = num1.plus(num2); - num2 = num1; - num1 = t; - } - return num1; -} -static void bigint_test_fibo500() -{ - { - I_TEST((BigInteger | Fibonacci500)); - bool pass = (bigint_fibonacci(500).words() == Vector { 315178285, 505575602, 1883328078, 125027121, 3649625763, 347570207, 74535262, 3832543808, 2472133297, 1600064941, 65273441 }); - - if (pass) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_addition_edgecases() -{ - { - I_TEST((BigInteger | Edge Cases)); - Crypto::UnsignedBigInteger num1; - Crypto::UnsignedBigInteger num2(70); - Crypto::UnsignedBigInteger num3 = num1.plus(num2); - bool pass = (num3 == num2); - pass &= (num1 == Crypto::UnsignedBigInteger(0)); - - if (pass) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Borrow with zero)); - Crypto::UnsignedBigInteger num1({ UINT32_MAX - 3, UINT32_MAX }); - Crypto::UnsignedBigInteger num2({ UINT32_MAX - 2, 0 }); - if (num1.plus(num2).words() == Vector { 4294967289, 0, 1 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Basic add to accumulator)); - Crypto::UnsignedBigInteger num1(10); - Crypto::UnsignedBigInteger num2(70); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 80 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to empty accumulator)); - Crypto::UnsignedBigInteger num1({}); - Crypto::UnsignedBigInteger num2(10); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 10 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to smaller accumulator)); - Crypto::UnsignedBigInteger num1(10); - Crypto::UnsignedBigInteger num2({ 10, 10 }); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 20, 10 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to accumulator with carry)); - Crypto::UnsignedBigInteger num1(UINT32_MAX - 1); - Crypto::UnsignedBigInteger num2(2); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 0, 1 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to accumulator with multiple carries)); - Crypto::UnsignedBigInteger num1({ UINT32_MAX - 2, UINT32_MAX - 1 }); - Crypto::UnsignedBigInteger num2({ 5, 1 }); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 2, 0, 1 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to accumulator with multiple carry levels)); - Crypto::UnsignedBigInteger num1({ UINT32_MAX - 2, UINT32_MAX }); - Crypto::UnsignedBigInteger num2(5); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 2, 0, 1 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to accumulator with leading zero)); - Crypto::UnsignedBigInteger num1(1); - Crypto::UnsignedBigInteger num2({ 1, 0 }); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 2 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Add to accumulator with carry and leading zero)); - Crypto::UnsignedBigInteger num1({ UINT32_MAX, 0, 0, 0 }); - Crypto::UnsignedBigInteger num2({ 1, 0 }); - Crypto::UnsignedBigIntegerAlgorithms::add_into_accumulator_without_allocation(num1, num2); - if (num1.words() == Vector { 0, 1, 0, 0 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_subtraction() -{ - { - I_TEST((BigInteger | Simple Subtraction 1)); - Crypto::UnsignedBigInteger num1(80); - Crypto::UnsignedBigInteger num2(70); - - if (num1.minus(num2) == Crypto::UnsignedBigInteger(10)) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Simple Subtraction 2)); - Crypto::UnsignedBigInteger num1(50); - Crypto::UnsignedBigInteger num2(70); - - if (num1.minus(num2).is_invalid()) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Subtraction with borrow)); - Crypto::UnsignedBigInteger num1(UINT32_MAX); - Crypto::UnsignedBigInteger num2(1); - Crypto::UnsignedBigInteger num3 = num1.plus(num2); - Crypto::UnsignedBigInteger result = num3.minus(num2); - if (result == num1) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Subtraction with large numbers)); - Crypto::UnsignedBigInteger num1 = bigint_fibonacci(343); - Crypto::UnsignedBigInteger num2 = bigint_fibonacci(218); - Crypto::UnsignedBigInteger result = num1.minus(num2); - if ((result.plus(num2) == num1) - && (result.words() == Vector { 811430588, 2958904896, 1130908877, 2830569969, 3243275482, 3047460725, 774025231, 7990 })) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Subtraction with large numbers 2)); - Crypto::UnsignedBigInteger num1(Vector { 1483061863, 446680044, 1123294122, 191895498, 3347106536, 16, 0, 0, 0 }); - Crypto::UnsignedBigInteger num2(Vector { 4196414175, 1117247942, 1123294122, 191895498, 3347106536, 16 }); - Crypto::UnsignedBigInteger result = num1.minus(num2); - // this test only verifies that we don't crash on an assertion - PASS; - } - { - I_TEST((BigInteger | Subtraction Regression 1)); - auto num = Crypto::UnsignedBigInteger { 1 }.shift_left(256); - if (num.minus(1).words() == Vector { 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 0 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_multiplication() -{ - { - I_TEST((BigInteger | Simple Multiplication)); - Crypto::UnsignedBigInteger num1(8); - Crypto::UnsignedBigInteger num2(251); - Crypto::UnsignedBigInteger result = num1.multiplied_by(num2); - if (result.words() == Vector { 2008 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Multiplications with big numbers 1)); - Crypto::UnsignedBigInteger num1 = bigint_fibonacci(200); - Crypto::UnsignedBigInteger num2(12345678); - Crypto::UnsignedBigInteger result = num1.multiplied_by(num2); - if (result.words() == Vector { 669961318, 143970113, 4028714974, 3164551305, 1589380278, 2 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Multiplications with big numbers 2)); - Crypto::UnsignedBigInteger num1 = bigint_fibonacci(200); - Crypto::UnsignedBigInteger num2 = bigint_fibonacci(341); - Crypto::UnsignedBigInteger result = num1.multiplied_by(num2); - if (result.words() == Vector { 3017415433, 2741793511, 1957755698, 3731653885, 3154681877, 785762127, 3200178098, 4260616581, 529754471, 3632684436, 1073347813, 2516430 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} -static void bigint_division() -{ - { - I_TEST((BigInteger | Simple Division)); - Crypto::UnsignedBigInteger num1(27194); - Crypto::UnsignedBigInteger num2(251); - auto result = num1.divided_by(num2); - Crypto::UnsignedDivisionResult expected = { Crypto::UnsignedBigInteger(108), Crypto::UnsignedBigInteger(86) }; - if (result.quotient == expected.quotient && result.remainder == expected.remainder) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Division with big numbers)); - Crypto::UnsignedBigInteger num1 = bigint_fibonacci(386); - Crypto::UnsignedBigInteger num2 = bigint_fibonacci(238); - auto result = num1.divided_by(num2); - Crypto::UnsignedDivisionResult expected = { - Crypto::UnsignedBigInteger(Vector { 2300984486, 2637503534, 2022805584, 107 }), - Crypto::UnsignedBigInteger(Vector { 1483061863, 446680044, 1123294122, 191895498, 3347106536, 16, 0, 0, 0 }) - }; - if (result.quotient == expected.quotient && result.remainder == expected.remainder) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Combined test)); - auto num1 = bigint_fibonacci(497); - auto num2 = bigint_fibonacci(238); - auto div_result = num1.divided_by(num2); - if (div_result.quotient.multiplied_by(num2).plus(div_result.remainder) == num1) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_base10() -{ - { - I_TEST((BigInteger | From String)); - auto result = Crypto::UnsignedBigInteger::from_base(10, "57195071295721390579057195715793"); - if (result.words() == Vector { 3806301393, 954919431, 3879607298, 721 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | To String)); - auto result = Crypto::UnsignedBigInteger { Vector { 3806301393, 954919431, 3879607298, 721 } }.to_base(10); - if (result == "57195071295721390579057195715793") { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_theory_modular_inverse() -{ - { - I_TEST((Number Theory | Modular Inverse)); - if (Crypto::NumberTheory::ModularInverse(7, 87) == 25) { - PASS; - } else { - FAIL(Invalid result); - } - } -} - -static void bigint_theory_modular_power() -{ - { - I_TEST((BigInteger | Simple Modular Power | Even)); - Crypto::UnsignedBigInteger base { 7 }; - Crypto::UnsignedBigInteger exponent { 2 }; - Crypto::UnsignedBigInteger modulo { 10 }; - auto result = Crypto::NumberTheory::ModularPower(base, exponent, modulo); - if (result.words() == Vector { 9 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Simple Modular Power | Odd)); - Crypto::UnsignedBigInteger base { 10 }; - Crypto::UnsignedBigInteger exponent { 2 }; - Crypto::UnsignedBigInteger modulo { 9 }; - auto result = Crypto::NumberTheory::ModularPower(base, exponent, modulo); - if (result.words() == Vector { 1 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Large Modular Power | Even Fibonacci)); - Crypto::UnsignedBigInteger base = bigint_fibonacci(200); - Crypto::UnsignedBigInteger exponent = bigint_fibonacci(100); - Crypto::UnsignedBigInteger modulo = bigint_fibonacci(150); - // Result according to Wolfram Alpha : 7195284628716783672927396027925 - auto result = Crypto::NumberTheory::ModularPower(base, exponent, modulo); - if (result.words() == Vector { 2042093077, 1351416233, 3510104665, 90 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Large Modular Power | Odd Fibonacci)); - Crypto::UnsignedBigInteger base = bigint_fibonacci(200); - Crypto::UnsignedBigInteger exponent = bigint_fibonacci(100); - Crypto::UnsignedBigInteger modulo = bigint_fibonacci(149); - // Result according to Wolfram Alpha : 1136278609611966596838389694992 - auto result = Crypto::NumberTheory::ModularPower(base, exponent, modulo); - if (result.words() == Vector { 2106049040, 2169509253, 1468244710, 14 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((BigInteger | Large Modular Power | Odd Fibonacci with carry)); - Crypto::UnsignedBigInteger base = bigint_fibonacci(200); - Crypto::UnsignedBigInteger exponent = bigint_fibonacci(100); - Crypto::UnsignedBigInteger modulo = bigint_fibonacci(185); - // Result according to Wolfram Alpha : 55094573983071006678665780782730672080 - auto result = Crypto::NumberTheory::ModularPower(base, exponent, modulo); - if (result.words() == Vector { 1988720592, 2097784252, 347129583, 695391288 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - - { - struct { - Crypto::UnsignedBigInteger base; - Crypto::UnsignedBigInteger exp; - Crypto::UnsignedBigInteger mod; - Crypto::UnsignedBigInteger expected; - } mod_pow_tests[] = { - { "2988348162058574136915891421498819466320163312926952423791023078876139"_bigint, "2351399303373464486466122544523690094744975233415544072992656881240319"_bigint, "10000"_bigint, "3059"_bigint }, - { "24231"_bigint, "12448"_bigint, "14679"_bigint, "4428"_bigint }, - { "1005404"_bigint, "8352654"_bigint, "8161408"_bigint, "2605696"_bigint }, - { "3665005778"_bigint, "3244425589"_bigint, "565668506"_bigint, "524766494"_bigint }, - { "10662083169959689657"_bigint, "11605678468317533000"_bigint, "1896834583057209739"_bigint, "1292743154593945858"_bigint }, - { "99667739213529524852296932424683448520"_bigint, "123394910770101395416306279070921784207"_bigint, "238026722756504133786938677233768788719"_bigint, "197165477545023317459748215952393063201"_bigint }, - { "49368547511968178788919424448914214709244872098814465088945281575062739912239"_bigint, "25201856190991298572337188495596990852134236115562183449699512394891190792064"_bigint, "45950460777961491021589776911422805972195170308651734432277141467904883064645"_bigint, "39917885806532796066922509794537889114718612292469285403012781055544152450051"_bigint }, - { "48399385336454791246880286907257136254351739111892925951016159217090949616810"_bigint, "5758661760571644379364752528081901787573279669668889744323710906207949658569"_bigint, "32812120644405991429173950312949738783216437173380339653152625840449006970808"_bigint, "7948464125034399875323770213514649646309423451213282653637296324080400293584"_bigint }, - }; - - for (auto test_case : mod_pow_tests) { - I_TEST((BigInteger | Modular Power | Several other test cases)); - auto actual = Crypto::NumberTheory::ModularPower( - test_case.base, test_case.exp, test_case.mod); - - if (actual == test_case.expected) { - PASS; - } else { - FAIL(Wrong result); - outln("b: {}", test_case.base.to_base(10)); - outln("e: {}", test_case.exp.to_base(10)); - outln("m: {}", test_case.mod.to_base(10)); - outln("expect: {}", test_case.expected.to_base(10)); - outln("actual: {}", actual.to_base(10)); - } - } - } -} - -static void bigint_theory_primality() -{ - struct { - Crypto::UnsignedBigInteger candidate; - bool expected_result; - } primality_tests[] = { - { "1180591620717411303424"_bigint, false }, // 2**70 - { "620448401733239439360000"_bigint, false }, // 25! - { "953962166440690129601298432"_bigint, false }, // 12**25 - { "620448401733239439360000"_bigint, false }, // 25! - { "147926426347074375"_bigint, false }, // 35! / 2**32 - { "340282366920938429742726440690708343523"_bigint, false }, // 2 factors near 2^64 - { "73"_bigint, true }, - { "6967"_bigint, true }, - { "787649"_bigint, true }, - { "73513949"_bigint, true }, - { "6691236901"_bigint, true }, - { "741387182759"_bigint, true }, - { "67466615915827"_bigint, true }, - { "9554317039214687"_bigint, true }, - { "533344522150170391"_bigint, true }, - { "18446744073709551557"_bigint, true }, // just below 2**64 - }; - - for (auto test_case : primality_tests) { - I_TEST((BigInteger | Primality)); - bool actual_result = Crypto::NumberTheory::is_probably_prime(test_case.candidate); - if (test_case.expected_result == actual_result) { - PASS; - } else { - FAIL(Wrong primality guess); - outln("The number {} is {}a prime, but the test said it is {}a prime!", - test_case.candidate.to_base(10), test_case.expected_result ? "" : "not ", actual_result ? "" : "not "); - } - } -} - -static void bigint_theory_random_number() -{ - { - struct { - Crypto::UnsignedBigInteger min; - Crypto::UnsignedBigInteger max; - } random_number_tests[] = { - { "1"_bigint, "1000000"_bigint }, - { "10000000000"_bigint, "20000000000"_bigint }, - { "1000"_bigint, "200000000000000000"_bigint }, - { "200000000000000000"_bigint, "200000000000010000"_bigint }, - }; - - for (auto test_case : random_number_tests) { - I_TEST((BigInteger | Random numbers)); - auto actual_result = Crypto::NumberTheory::random_number(test_case.min, test_case.max); - if (actual_result < test_case.min) { - FAIL(Too small); - outln("The generated number {} is smaller than the requested minimum {}. (max = {})", actual_result.to_base(10), test_case.min.to_base(10), test_case.max.to_base(10)); - } else if (!(actual_result < test_case.max)) { - FAIL(Too large); - outln("The generated number {} is larger-or-equal to the requested maximum {}. (min = {})", actual_result.to_base(10), test_case.max.to_base(10), test_case.min.to_base(10)); - } else { - PASS; - } - } - } - { - I_TEST((BigInteger | Random distribution)); - auto actual_result = Crypto::NumberTheory::random_number( - "1"_bigint, - "100000000000000000000000000000"_bigint); // 10**29 - if (actual_result < "100000000000000000000"_bigint) { // 10**20 - FAIL(Too small); - outln("The generated number {} is extremely small. This *can* happen by pure chance, but should happen only once in a billion times. So it's probably an error.", actual_result.to_base(10)); - } else if ("99999999900000000000000000000"_bigint < actual_result) { // 10**29 - 10**20 - FAIL(Too large); - outln("The generated number {} is extremely large. This *can* happen by pure chance, but should happen only once in a billion times. So it's probably an error.", actual_result.to_base(10)); - } else { - PASS; - } - } -} - -static void bigint_import_export() -{ - { - I_TEST((BigInteger | BigEndian Decode / Encode roundtrip)); - u8 random_bytes[128]; - u8 target_buffer[128]; - fill_with_random(random_bytes, 128); - auto encoded = Crypto::UnsignedBigInteger::import_data(random_bytes, 128); - encoded.export_data({ target_buffer, 128 }); - if (memcmp(target_buffer, random_bytes, 128) != 0) - FAIL(Could not roundtrip); - else - PASS; - } - { - I_TEST((BigInteger | BigEndian Encode / Decode roundtrip)); - u8 target_buffer[128]; - auto encoded = "12345678901234567890"_bigint; - auto size = encoded.export_data({ target_buffer, 128 }); - auto decoded = Crypto::UnsignedBigInteger::import_data(target_buffer, size); - if (encoded != decoded) - FAIL(Could not roundtrip); - else - PASS; - } - { - I_TEST((BigInteger | BigEndian Import)); - auto number = Crypto::UnsignedBigInteger::import_data("hello"); - if (number == "448378203247"_bigint) { - PASS; - } else { - FAIL(Invalid value); - } - } - { - I_TEST((BigInteger | BigEndian Export)); - auto number = "448378203247"_bigint; - char exported[8] { 0 }; - auto exported_length = number.export_data({ exported, 8 }, true); - if (exported_length == 5 && memcmp(exported + 3, "hello", 5) == 0) { - PASS; - } else { - FAIL(Invalid value); - print_buffer({ exported - exported_length + 8, exported_length }, -1); - } - } -} - -static void bigint_bitwise() -{ - { - I_TEST((BigInteger | Basic bitwise or)); - auto num1 = "1234567"_bigint; - auto num2 = "1234567"_bigint; - if (num1.bitwise_or(num2) == num1) { - PASS; - } else { - FAIL(Invalid value); - } - } - { - I_TEST((BigInteger | Bitwise or handles different lengths)); - auto num1 = "1234567"_bigint; - auto num2 = "123456789012345678901234567890"_bigint; - auto expected = "123456789012345678901234622167"_bigint; - auto result = num1.bitwise_or(num2); - if (result == expected) { - PASS; - } else { - FAIL(Invalid value); - } - } - { - I_TEST((BigInteger | Basic bitwise and)); - auto num1 = "1234567"_bigint; - auto num2 = "1234561"_bigint; - if (num1.bitwise_and(num2) == "1234561"_bigint) { - PASS; - } else { - FAIL(Invalid value); - } - } - { - I_TEST((BigInteger | Bitwise and handles different lengths)); - auto num1 = "1234567"_bigint; - auto num2 = "123456789012345678901234567890"_bigint; - if (num1.bitwise_and(num2) == "1180290"_bigint) { - PASS; - } else { - FAIL(Invalid value); - } - } - { - I_TEST((BigInteger | Basic bitwise xor)); - auto num1 = "1234567"_bigint; - auto num2 = "1234561"_bigint; - if (num1.bitwise_xor(num2) == 6) { - PASS; - } else { - FAIL(Invalid value); - } - } - { - I_TEST((BigInteger | Bitwise xor handles different lengths)); - auto num1 = "1234567"_bigint; - auto num2 = "123456789012345678901234567890"_bigint; - if (num1.bitwise_xor(num2) == "123456789012345678901233441877"_bigint) { - PASS; - } else { - FAIL(Invalid value); - } - } -} - -static void bigint_test_signed_fibo500() -{ - { - I_TEST((Signed BigInteger | Fibonacci500)); - bool pass = (bigint_signed_fibonacci(500).unsigned_value().words() == Vector { 315178285, 505575602, 1883328078, 125027121, 3649625763, 347570207, 74535262, 3832543808, 2472133297, 1600064941, 65273441 }); - - if (pass) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_signed_addition_edgecases() -{ - { - I_TEST((Signed BigInteger | Borrow with zero)); - Crypto::SignedBigInteger num1 { Crypto::UnsignedBigInteger { { UINT32_MAX - 3, UINT32_MAX } }, false }; - Crypto::SignedBigInteger num2 { Crypto::UnsignedBigInteger { UINT32_MAX - 2 }, false }; - if (num1.plus(num2).unsigned_value().words() == Vector { 4294967289, 0, 1 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Addition to other sign)); - Crypto::SignedBigInteger num1 = INT32_MAX; - Crypto::SignedBigInteger num2 = num1; - num2.negate(); - if (num1.plus(num2) == Crypto::SignedBigInteger { 0 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_signed_subtraction() -{ - { - I_TEST((Signed BigInteger | Simple Subtraction 1)); - Crypto::SignedBigInteger num1(80); - Crypto::SignedBigInteger num2(70); - - if (num1.minus(num2) == Crypto::SignedBigInteger(10)) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Simple Subtraction 2)); - Crypto::SignedBigInteger num1(50); - Crypto::SignedBigInteger num2(70); - - if (num1.minus(num2) == Crypto::SignedBigInteger { -20 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Subtraction with borrow)); - Crypto::SignedBigInteger num1(Crypto::UnsignedBigInteger { UINT32_MAX }); - Crypto::SignedBigInteger num2(1); - Crypto::SignedBigInteger num3 = num1.plus(num2); - Crypto::SignedBigInteger result = num2.minus(num3); - num1.negate(); - if (result == num1) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Subtraction with large numbers)); - Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(343); - Crypto::SignedBigInteger num2 = bigint_signed_fibonacci(218); - Crypto::SignedBigInteger result = num2.minus(num1); - auto expected = Crypto::UnsignedBigInteger { Vector { 811430588, 2958904896, 1130908877, 2830569969, 3243275482, 3047460725, 774025231, 7990 } }; - if ((result.plus(num1) == num2) - && (result.unsigned_value() == expected)) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Subtraction with large numbers 2)); - Crypto::SignedBigInteger num1(Crypto::UnsignedBigInteger { Vector { 1483061863, 446680044, 1123294122, 191895498, 3347106536, 16, 0, 0, 0 } }); - Crypto::SignedBigInteger num2(Crypto::UnsignedBigInteger { Vector { 4196414175, 1117247942, 1123294122, 191895498, 3347106536, 16 } }); - Crypto::SignedBigInteger result = num1.minus(num2); - // this test only verifies that we don't crash on an assertion - PASS; - } -} - -static void bigint_signed_multiplication() -{ - { - I_TEST((Signed BigInteger | Simple Multiplication)); - Crypto::SignedBigInteger num1(8); - Crypto::SignedBigInteger num2(-251); - Crypto::SignedBigInteger result = num1.multiplied_by(num2); - if (result == Crypto::SignedBigInteger { -2008 }) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Multiplications with big numbers 1)); - Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(200); - Crypto::SignedBigInteger num2(-12345678); - Crypto::SignedBigInteger result = num1.multiplied_by(num2); - if (result.unsigned_value().words() == Vector { 669961318, 143970113, 4028714974, 3164551305, 1589380278, 2 } && result.is_negative()) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Multiplications with big numbers 2)); - Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(200); - Crypto::SignedBigInteger num2 = bigint_signed_fibonacci(341); - num1.negate(); - Crypto::SignedBigInteger result = num1.multiplied_by(num2); - if (result.unsigned_value().words() == Vector { 3017415433, 2741793511, 1957755698, 3731653885, 3154681877, 785762127, 3200178098, 4260616581, 529754471, 3632684436, 1073347813, 2516430 } && result.is_negative()) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} -static void bigint_signed_division() -{ - { - I_TEST((Signed BigInteger | Simple Division)); - Crypto::SignedBigInteger num1(27194); - Crypto::SignedBigInteger num2(-251); - auto result = num1.divided_by(num2); - Crypto::SignedDivisionResult expected = { Crypto::SignedBigInteger(-108), Crypto::SignedBigInteger(86) }; - if (result.quotient == expected.quotient && result.remainder == expected.remainder) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Division with big numbers)); - Crypto::SignedBigInteger num1 = bigint_signed_fibonacci(386); - Crypto::SignedBigInteger num2 = bigint_signed_fibonacci(238); - num1.negate(); - auto result = num1.divided_by(num2); - Crypto::SignedDivisionResult expected = { - Crypto::SignedBigInteger(Crypto::UnsignedBigInteger { Vector { 2300984486, 2637503534, 2022805584, 107 } }, true), - Crypto::SignedBigInteger(Crypto::UnsignedBigInteger { Vector { 1483061863, 446680044, 1123294122, 191895498, 3347106536, 16, 0, 0, 0 } }, true) - }; - if (result.quotient == expected.quotient && result.remainder == expected.remainder) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | Combined test)); - auto num1 = bigint_signed_fibonacci(497); - auto num2 = bigint_signed_fibonacci(238); - num1.negate(); - auto div_result = num1.divided_by(num2); - if (div_result.quotient.multiplied_by(num2).plus(div_result.remainder) == num1) { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_signed_base10() -{ - { - I_TEST((Signed BigInteger | From String)); - auto result = Crypto::SignedBigInteger::from_base(10, "-57195071295721390579057195715793"); - if (result.unsigned_value().words() == Vector { 3806301393, 954919431, 3879607298, 721 } && result.is_negative()) { - PASS; - } else { - FAIL(Incorrect Result); - } - } - { - I_TEST((Signed BigInteger | To String)); - auto result = Crypto::SignedBigInteger { Crypto::UnsignedBigInteger { Vector { 3806301393, 954919431, 3879607298, 721 } }, true }.to_base(10); - if (result == "-57195071295721390579057195715793") { - PASS; - } else { - FAIL(Incorrect Result); - } - } -} - -static void bigint_signed_import_export() -{ - { - I_TEST((Signed BigInteger | BigEndian Decode / Encode roundtrip)); - u8 random_bytes[129]; - u8 target_buffer[129]; - random_bytes[0] = 1; - fill_with_random(random_bytes + 1, 128); - auto encoded = Crypto::SignedBigInteger::import_data(random_bytes, 129); - encoded.export_data({ target_buffer, 129 }); - if (memcmp(target_buffer, random_bytes, 129) != 0) - FAIL(Could not roundtrip); - else - PASS; - } - { - I_TEST((Signed BigInteger | BigEndian Encode / Decode roundtrip)); - u8 target_buffer[128]; - auto encoded = "-12345678901234567890"_sbigint; - auto size = encoded.export_data({ target_buffer, 128 }); - auto decoded = Crypto::SignedBigInteger::import_data(target_buffer, size); - if (encoded != decoded) - FAIL(Could not roundtrip); - else - PASS; - } -} - -static void bigint_signed_bitwise() -{ - { - I_TEST((Signed BigInteger | Bitwise or handles sign)); - auto num1 = "-1234567"_sbigint; - auto num2 = "1234567"_sbigint; - if (num1.bitwise_or(num2) == "-1"_sbigint) { - PASS; - } else { - FAIL(Invalid value); - } - } -}