tests/core/crypto: Use the tests/common boilerplate

This commit is contained in:
Yawning Angel
2024-03-04 17:38:53 +09:00
parent fa8dd5a13b
commit 87ab3f5dc8
8 changed files with 87 additions and 107 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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),
)