From 87ab3f5dc87dd64f3d7f55cabf1545be8998e997 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Mon, 4 Mar 2024 17:38:53 +0900 Subject: [PATCH] tests/core/crypto: Use the `tests/common` boilerplate --- tests/core/Makefile | 2 +- tests/core/build.bat | 2 +- tests/core/crypto/test_core_crypto.odin | 76 ++++++------------- tests/core/crypto/test_core_crypto_hash.odin | 42 +++++----- tests/core/crypto/test_core_crypto_kdf.odin | 12 +-- tests/core/crypto/test_core_crypto_mac.odin | 20 ++--- .../test_core_crypto_sha3_variants.odin | 20 ++--- tests/core/crypto/test_crypto_benchmark.odin | 20 ++--- 8 files changed, 87 insertions(+), 107 deletions(-) diff --git a/tests/core/Makefile b/tests/core/Makefile index 1207eeec5..ecb05d002 100644 --- a/tests/core/Makefile +++ b/tests/core/Makefile @@ -45,7 +45,7 @@ hash_test: $(ODIN) run hash $(COMMON) -o:speed -no-bounds-check -out:test_hash crypto_test: - $(ODIN) run crypto $(COMMON) -o:speed -no-bounds-check -out:test_crypto + $(ODIN) run crypto $(COMMON) $(COLLECTION) -o:speed -no-bounds-check -out:test_crypto noise_test: $(ODIN) run math/noise $(COMMON) -out:test_noise diff --git a/tests/core/build.bat b/tests/core/build.bat index d5f528f0c..210760d00 100644 --- a/tests/core/build.bat +++ b/tests/core/build.bat @@ -31,7 +31,7 @@ echo --- echo --- echo Running core:crypto tests echo --- -%PATH_TO_ODIN% run crypto %COMMON% -out:test_crypto.exe || exit /b +%PATH_TO_ODIN% run crypto %COMMON% %COLLECTION% -out:test_crypto.exe || exit /b echo --- echo Running core:encoding tests diff --git a/tests/core/crypto/test_core_crypto.odin b/tests/core/crypto/test_core_crypto.odin index da4f53f43..a6d399097 100644 --- a/tests/core/crypto/test_core_crypto.odin +++ b/tests/core/crypto/test_core_crypto.odin @@ -15,35 +15,14 @@ package test_core_crypto import "core:encoding/hex" import "core:fmt" import "core:mem" -import "core:os" import "core:testing" import "core:crypto" import "core:crypto/chacha20" import "core:crypto/chacha20poly1305" - import "core:crypto/x25519" -TEST_count := 0 -TEST_fail := 0 - -when ODIN_TEST { - expect :: testing.expect - log :: testing.log -} else { - expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { - TEST_count += 1 - if !condition { - TEST_fail += 1 - fmt.printf("[%v] %v\n", loc, message) - return - } - } - log :: proc(t: ^testing.T, v: any, loc := #caller_location) { - fmt.printf("[%v] ", loc) - fmt.printf("log: %v\n", v) - } -} +import tc "tests:common" main :: proc() { t := testing.T{} @@ -61,17 +40,14 @@ main :: proc() { bench_crypto(&t) - fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) - if TEST_fail > 0 { - os.exit(1) - } + tc.report(&t) } _PLAINTEXT_SUNSCREEN_STR := "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it." @(test) test_chacha20 :: proc(t: ^testing.T) { - log(t, "Testing (X)ChaCha20") + tc.log(t, "Testing (X)ChaCha20") // Test cases taken from RFC 8439, and draft-irtf-cfrg-xchacha-03 plaintext := transmute([]byte)(_PLAINTEXT_SUNSCREEN_STR) @@ -114,7 +90,7 @@ test_chacha20 :: proc(t: ^testing.T) { chacha20.xor_bytes(&ctx, derived_ciphertext[:], plaintext[:]) derived_ciphertext_str := string(hex.encode(derived_ciphertext[:], context.temp_allocator)) - expect( + tc.expect( t, derived_ciphertext_str == ciphertext_str, fmt.tprintf( @@ -161,7 +137,7 @@ test_chacha20 :: proc(t: ^testing.T) { chacha20.xor_bytes(&ctx, derived_ciphertext[:], plaintext[:]) derived_ciphertext_str = string(hex.encode(derived_ciphertext[:], context.temp_allocator)) - expect( + tc.expect( t, derived_ciphertext_str == xciphertext_str, fmt.tprintf( @@ -174,7 +150,7 @@ test_chacha20 :: proc(t: ^testing.T) { @(test) test_chacha20poly1305 :: proc(t: ^testing.T) { - log(t, "Testing chacha20poly1205") + tc.log(t, "Testing chacha20poly1205") plaintext := transmute([]byte)(_PLAINTEXT_SUNSCREEN_STR) @@ -233,7 +209,7 @@ test_chacha20poly1305 :: proc(t: ^testing.T) { ) derived_ciphertext_str := string(hex.encode(derived_ciphertext[:], context.temp_allocator)) - expect( + tc.expect( t, derived_ciphertext_str == ciphertext_str, fmt.tprintf( @@ -244,7 +220,7 @@ test_chacha20poly1305 :: proc(t: ^testing.T) { ) derived_tag_str := string(hex.encode(derived_tag[:], context.temp_allocator)) - expect( + tc.expect( t, derived_tag_str == tag_str, fmt.tprintf( @@ -264,8 +240,8 @@ test_chacha20poly1305 :: proc(t: ^testing.T) { ciphertext[:], ) derived_plaintext_str := string(derived_plaintext[:]) - expect(t, ok, "Expected true for decrypt(tag, aad, ciphertext)") - expect( + tc.expect(t, ok, "Expected true for decrypt(tag, aad, ciphertext)") + tc.expect( t, derived_plaintext_str == _PLAINTEXT_SUNSCREEN_STR, fmt.tprintf( @@ -284,7 +260,7 @@ test_chacha20poly1305 :: proc(t: ^testing.T) { aad[:], derived_ciphertext[:], ) - expect(t, !ok, "Expected false for decrypt(tag, aad, corrupted_ciphertext)") + tc.expect(t, !ok, "Expected false for decrypt(tag, aad, corrupted_ciphertext)") aad[0] ~= 0xa5 ok = chacha20poly1305.decrypt( @@ -295,18 +271,12 @@ test_chacha20poly1305 :: proc(t: ^testing.T) { aad[:], ciphertext[:], ) - expect(t, !ok, "Expected false for decrypt(tag, corrupted_aad, ciphertext)") -} - -TestECDH :: struct { - scalar: string, - point: string, - product: string, + tc.expect(t, !ok, "Expected false for decrypt(tag, corrupted_aad, ciphertext)") } @(test) test_x25519 :: proc(t: ^testing.T) { - log(t, "Testing X25519") + tc.log(t, "Testing X25519") // Local copy of this so that the base point doesn't need to be exported. _BASE_POINT: [32]byte = { @@ -314,7 +284,11 @@ test_x25519 :: proc(t: ^testing.T) { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } - test_vectors := [?]TestECDH { + test_vectors := []struct{ + scalar: string, + point: string, + product: string, + } { // Test vectors from RFC 7748 { "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", @@ -335,7 +309,7 @@ test_x25519 :: proc(t: ^testing.T) { x25519.scalarmult(derived_point[:], scalar[:], point[:]) derived_point_str := string(hex.encode(derived_point[:], context.temp_allocator)) - expect( + tc.expect( t, derived_point_str == v.product, fmt.tprintf( @@ -353,7 +327,7 @@ test_x25519 :: proc(t: ^testing.T) { x25519.scalarmult(p2[:], scalar[:], _BASE_POINT[:]) p1_str := string(hex.encode(p1[:], context.temp_allocator)) p2_str := string(hex.encode(p2[:], context.temp_allocator)) - expect( + tc.expect( t, p1_str == p2_str, fmt.tprintf( @@ -371,16 +345,14 @@ test_x25519 :: proc(t: ^testing.T) { @(test) test_rand_bytes :: proc(t: ^testing.T) { - log(t, "Testing rand_bytes") + tc.log(t, "Testing rand_bytes") if ODIN_OS != .Linux { - log(t, "rand_bytes not supported - skipping") + tc.log(t, "rand_bytes not supported - skipping") return } - allocator := context.allocator - - buf := make([]byte, 1 << 25, allocator) + buf := make([]byte, 1 << 25, context.allocator) defer delete(buf) // Testing a CSPRNG for correctness is incredibly involved and @@ -405,7 +377,7 @@ test_rand_bytes :: proc(t: ^testing.T) { } } - expect( + tc.expect( t, seems_ok, "Expected to randomize the head and tail of the buffer within a handful of attempts", diff --git a/tests/core/crypto/test_core_crypto_hash.odin b/tests/core/crypto/test_core_crypto_hash.odin index 7dc559681..bd40a9b23 100644 --- a/tests/core/crypto/test_core_crypto_hash.odin +++ b/tests/core/crypto/test_core_crypto_hash.odin @@ -8,22 +8,22 @@ import "core:testing" import "core:crypto/hash" -TestHash :: struct { - algo: hash.Algorithm, - hash: string, - str: string, -} +import tc "tests:common" @(test) test_hash :: proc(t: ^testing.T) { - log(t, "Testing Hashes") + tc.log(t, "Testing Hashes") // TODO: // - Stick the test vectors in a JSON file or something. data_1_000_000_a := strings.repeat("a", 1_000_000) - digest: [64]byte // 512-bits is enough for every digest for now. - test_vectors := [?]TestHash { + digest: [hash.MAX_DIGEST_SIZE]byte + test_vectors := []struct{ + algo: hash.Algorithm, + hash: string, + str: string, + } { // BLAKE2b { hash.Algorithm.BLAKE2B, @@ -424,9 +424,9 @@ test_hash :: proc(t: ^testing.T) { // MD5 (Insecure) // - https://datatracker.ietf.org/doc/html/rfc1321 - TestHash{hash.Algorithm.Insecure_MD5, "d41d8cd98f00b204e9800998ecf8427e", ""}, - TestHash{hash.Algorithm.Insecure_MD5, "0cc175b9c0f1b6a831c399e269772661", "a"}, - TestHash{hash.Algorithm.Insecure_MD5, "900150983cd24fb0d6963f7d28e17f72", "abc"}, + {hash.Algorithm.Insecure_MD5, "d41d8cd98f00b204e9800998ecf8427e", ""}, + {hash.Algorithm.Insecure_MD5, "0cc175b9c0f1b6a831c399e269772661", "a"}, + {hash.Algorithm.Insecure_MD5, "900150983cd24fb0d6963f7d28e17f72", "abc"}, { hash.Algorithm.Insecure_MD5, "f96b697d7cb7938d525a2f31aaf161d0", @@ -451,8 +451,8 @@ test_hash :: proc(t: ^testing.T) { // SHA-1 (Insecure) // - https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf // - https://www.di-mgt.com.au/sha_testvectors.html - TestHash{hash.Algorithm.Insecure_SHA1, "da39a3ee5e6b4b0d3255bfef95601890afd80709", ""}, - TestHash{hash.Algorithm.Insecure_SHA1, "a9993e364706816aba3e25717850c26c9cd0d89d", "abc"}, + {hash.Algorithm.Insecure_SHA1, "da39a3ee5e6b4b0d3255bfef95601890afd80709", ""}, + {hash.Algorithm.Insecure_SHA1, "a9993e364706816aba3e25717850c26c9cd0d89d", "abc"}, { hash.Algorithm.Insecure_SHA1, "f9537c23893d2014f365adf8ffe33b8eb0297ed1", @@ -463,7 +463,7 @@ test_hash :: proc(t: ^testing.T) { "346fb528a24b48f563cb061470bcfd23740427ad", "jkijkljklmklmnlmnomnopnopq", }, - TestHash{hash.Algorithm.Insecure_SHA1, "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a"}, + {hash.Algorithm.Insecure_SHA1, "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8", "a"}, { hash.Algorithm.Insecure_SHA1, "c729c8996ee0a6f74f4f3248e8957edf704fb624", @@ -493,7 +493,7 @@ test_hash :: proc(t: ^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.hash, fmt.tprintf( @@ -518,7 +518,7 @@ test_hash :: proc(t: ^testing.T) { // still correct. digest_sz := hash.DIGEST_SIZES[algo] block_sz := hash.BLOCK_SIZES[algo] - expect( + tc.expect( t, digest_sz <= hash.MAX_DIGEST_SIZE, fmt.tprintf( @@ -528,7 +528,7 @@ test_hash :: proc(t: ^testing.T) { hash.MAX_DIGEST_SIZE, ), ) - expect( + tc.expect( t, block_sz <= hash.MAX_BLOCK_SIZE, fmt.tprintf( @@ -550,7 +550,7 @@ test_hash :: proc(t: ^testing.T) { a_str := string(hex.encode(digest_a, context.temp_allocator)) b_str := string(hex.encode(digest_b, context.temp_allocator)) - expect( + tc.expect( t, a_str == b_str, fmt.tprintf( @@ -568,7 +568,7 @@ test_hash :: proc(t: ^testing.T) { api_algo := hash.algorithm(&ctx) api_digest_size := hash.digest_size(&ctx) - expect( + tc.expect( t, algo == api_algo, fmt.tprintf( @@ -578,7 +578,7 @@ test_hash :: proc(t: ^testing.T) { api_algo, ), ) - expect( + tc.expect( t, hash.DIGEST_SIZES[algo] == api_digest_size, fmt.tprintf( @@ -601,7 +601,7 @@ test_hash :: proc(t: ^testing.T) { b_str = string(hex.encode(digest_b, context.temp_allocator)) c_str := string(hex.encode(digest_c, context.temp_allocator)) - expect( + tc.expect( t, a_str == b_str && b_str == c_str, fmt.tprintf( diff --git a/tests/core/crypto/test_core_crypto_kdf.odin b/tests/core/crypto/test_core_crypto_kdf.odin index f5ebf57f1..d9e9a8501 100644 --- a/tests/core/crypto/test_core_crypto_kdf.odin +++ b/tests/core/crypto/test_core_crypto_kdf.odin @@ -8,9 +8,11 @@ import "core:crypto/hash" import "core:crypto/hkdf" import "core:crypto/pbkdf2" +import tc "tests:common" + @(test) test_kdf :: proc(t: ^testing.T) { - log(t, "Testing KDFs") + tc.log(t, "Testing KDFs") test_hkdf(t) test_pbkdf2(t) @@ -18,7 +20,7 @@ test_kdf :: proc(t: ^testing.T) { @(test) test_hkdf :: proc(t: ^testing.T) { - log(t, "Testing HKDF") + tc.log(t, "Testing HKDF") tmp: [128]byte // Good enough. @@ -65,7 +67,7 @@ test_hkdf :: proc(t: ^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.okm, fmt.tprintf( @@ -83,7 +85,7 @@ test_hkdf :: proc(t: ^testing.T) { @(test) test_pbkdf2 :: proc(t: ^testing.T) { - log(t, "Testing PBKDF2") + tc.log(t, "Testing PBKDF2") tmp: [64]byte // 512-bits is enough for every output for now. @@ -169,7 +171,7 @@ test_pbkdf2 :: proc(t: ^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.dk, fmt.tprintf( diff --git a/tests/core/crypto/test_core_crypto_mac.odin b/tests/core/crypto/test_core_crypto_mac.odin index c9ee0f0f7..f0e6fa1bf 100644 --- a/tests/core/crypto/test_core_crypto_mac.odin +++ b/tests/core/crypto/test_core_crypto_mac.odin @@ -10,9 +10,11 @@ import "core:crypto/hmac" import "core:crypto/poly1305" import "core:crypto/siphash" +import tc "tests:common" + @(test) test_mac :: proc(t: ^testing.T) { - log(t, "Testing MACs") + tc.log(t, "Testing MACs") test_hmac(t) test_poly1305(t) @@ -81,7 +83,7 @@ test_hmac :: proc(t: ^testing.T) { msg_str := string(hex.encode(msg, context.temp_allocator)) dst_str := string(hex.encode(dst[:tag_len], context.temp_allocator)) - expect( + tc.expect( t, dst_str == expected_str, fmt.tprintf( @@ -97,7 +99,7 @@ test_hmac :: proc(t: ^testing.T) { hmac.sum(algo, dst, msg, key) oneshot_str := string(hex.encode(dst[:tag_len], context.temp_allocator)) - expect( + tc.expect( t, oneshot_str == expected_str, fmt.tprintf( @@ -114,7 +116,7 @@ test_hmac :: proc(t: ^testing.T) { @(test) test_poly1305 :: proc(t: ^testing.T) { - log(t, "Testing poly1305") + tc.log(t, "Testing poly1305") // Test cases taken from poly1305-donna. key := [poly1305.KEY_SIZE]byte { @@ -152,13 +154,13 @@ test_poly1305 :: proc(t: ^testing.T) { // Verify - oneshot + compare ok := poly1305.verify(tag[:], msg[:], key[:]) - expect(t, ok, "oneshot verify call failed") + tc.expect(t, ok, "oneshot verify call failed") // Sum - oneshot derived_tag: [poly1305.TAG_SIZE]byte poly1305.sum(derived_tag[:], msg[:], key[:]) derived_tag_str := string(hex.encode(derived_tag[:], context.temp_allocator)) - expect( + tc.expect( t, derived_tag_str == tag_str, fmt.tprintf("Expected %s for sum(msg, key), but got %s instead", tag_str, derived_tag_str), @@ -177,7 +179,7 @@ test_poly1305 :: proc(t: ^testing.T) { } poly1305.final(&ctx, derived_tag[:]) derived_tag_str = string(hex.encode(derived_tag[:], context.temp_allocator)) - expect( + tc.expect( t, derived_tag_str == tag_str, fmt.tprintf( @@ -190,7 +192,7 @@ test_poly1305 :: proc(t: ^testing.T) { @(test) test_siphash_2_4 :: proc(t: ^testing.T) { - log(t, "Testing SipHash-2-4") + tc.log(t, "Testing SipHash-2-4") // Test vectors from // https://github.com/veorq/SipHash/blob/master/vectors.h @@ -227,7 +229,7 @@ test_siphash_2_4 :: proc(t: ^testing.T) { vector := test_vectors[i] computed := siphash.sum_2_4(data[:], key[:]) - expect( + tc.expect( t, computed == vector, fmt.tprintf( diff --git a/tests/core/crypto/test_core_crypto_sha3_variants.odin b/tests/core/crypto/test_core_crypto_sha3_variants.odin index 2f591b11e..ec2d24331 100644 --- a/tests/core/crypto/test_core_crypto_sha3_variants.odin +++ b/tests/core/crypto/test_core_crypto_sha3_variants.odin @@ -8,9 +8,11 @@ import "core:crypto/kmac" import "core:crypto/shake" import "core:crypto/tuplehash" +import tc "tests:common" + @(test) test_sha3_variants :: proc(t: ^testing.T) { - log(t, "Testing SHA3 derived functions") + tc.log(t, "Testing SHA3 derived functions") test_shake(t) test_cshake(t) @@ -20,7 +22,7 @@ test_sha3_variants :: proc(t: ^testing.T) { @(test) test_shake :: proc(t: ^testing.T) { - log(t, "Testing SHAKE") + tc.log(t, "Testing SHAKE") test_vectors := []struct { sec_strength: int, @@ -62,7 +64,7 @@ test_shake :: proc(t: ^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.output, fmt.tprintf( @@ -78,7 +80,7 @@ test_shake :: proc(t: ^testing.T) { @(test) test_cshake :: proc(t: ^testing.T) { - log(t, "Testing cSHAKE") + tc.log(t, "Testing cSHAKE") test_vectors := []struct { sec_strength: int, @@ -136,7 +138,7 @@ test_cshake :: proc(t: ^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.output, fmt.tprintf( @@ -152,7 +154,7 @@ test_cshake :: proc(t: ^testing.T) { @(test) test_tuplehash :: proc(t: ^testing.T) { - log(t, "Testing TupleHash(XOF)") + tc.log(t, "Testing TupleHash(XOF)") test_vectors := []struct { sec_strength: int, @@ -327,7 +329,7 @@ test_tuplehash :: proc(t: ^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.output, fmt.tprintf( @@ -344,7 +346,7 @@ test_tuplehash :: proc(t: ^testing.T) { @(test) test_kmac :: proc(t:^testing.T) { - log(t, "Testing KMAC") + tc.log(t, "Testing KMAC") test_vectors := []struct { sec_strength: int, @@ -422,7 +424,7 @@ test_kmac :: proc(t:^testing.T) { dst_str := string(hex.encode(dst, context.temp_allocator)) - expect( + tc.expect( t, dst_str == v.output, fmt.tprintf( diff --git a/tests/core/crypto/test_crypto_benchmark.odin b/tests/core/crypto/test_crypto_benchmark.odin index cadcf8bec..494913b6b 100644 --- a/tests/core/crypto/test_crypto_benchmark.odin +++ b/tests/core/crypto/test_crypto_benchmark.odin @@ -10,6 +10,8 @@ import "core:crypto/chacha20poly1305" import "core:crypto/poly1305" import "core:crypto/x25519" +import tc "tests:common" + // Cryptographic primitive benchmarks. @(test) @@ -150,19 +152,19 @@ bench_chacha20 :: proc(t: ^testing.T) { } err := time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) name = "ChaCha20 1024 bytes" options.bytes = 1024 err = time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) name = "ChaCha20 65536 bytes" options.bytes = 65536 err = time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) } @@ -177,13 +179,13 @@ bench_poly1305 :: proc(t: ^testing.T) { } err := time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) name = "Poly1305 1024 zero bytes" options.bytes = 1024 err = time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) } @@ -198,19 +200,19 @@ bench_chacha20poly1305 :: proc(t: ^testing.T) { } err := time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) name = "chacha20poly1305 1024 bytes" options.bytes = 1024 err = time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) name = "chacha20poly1305 65536 bytes" options.bytes = 65536 err = time.benchmark(options, context.allocator) - expect(t, err == nil, name) + tc.expect(t, err == nil, name) benchmark_print(name, options) } @@ -229,7 +231,7 @@ bench_x25519 :: proc(t: ^testing.T) { } elapsed := time.since(start) - log( + tc.log( t, fmt.tprintf("x25519.scalarmult: ~%f us/op", time.duration_microseconds(elapsed) / iters), )