diff options
author | tb <> | 2025-09-08 08:11:49 +0000 |
---|---|---|
committer | tb <> | 2025-09-08 08:11:49 +0000 |
commit | 731703a848224f9ac266b1a4d87d2d47caf9c57d (patch) | |
tree | 99702660ce7c8d74dbe0f9726757ab74634f5fe5 /src | |
parent | 50734a3ae2c1320cf87d475e9d62636b532c8e90 (diff) | |
download | openbsd-731703a848224f9ac266b1a4d87d2d47caf9c57d.tar.gz openbsd-731703a848224f9ac266b1a4d87d2d47caf9c57d.tar.bz2 openbsd-731703a848224f9ac266b1a4d87d2d47caf9c57d.zip |
wycheproof: rework test selection
Since this has grown organically, the test selection has become a weird mix
of globs, regexes and test variants and it is hard to reason about what is
run and why. Instead, load all the json files from testvectors_v1/ and look
at algorithm (almost always available) and test schema to figure out if we
support it in libcrypto and the test harness. This separates the logic of
the test runner better from the test selection. Also make it a fatal error
if we don't explicitly skip an unknown algorithm.
Diffstat (limited to 'src')
-rw-r--r-- | src/regress/lib/libcrypto/wycheproof/wycheproof.go | 151 |
1 files changed, 82 insertions, 69 deletions
diff --git a/src/regress/lib/libcrypto/wycheproof/wycheproof.go b/src/regress/lib/libcrypto/wycheproof/wycheproof.go index 4b0a4c587c..db31383bc8 100644 --- a/src/regress/lib/libcrypto/wycheproof/wycheproof.go +++ b/src/regress/lib/libcrypto/wycheproof/wycheproof.go | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: wycheproof.go,v 1.188 2025/09/08 08:00:47 tb Exp $ */ | 1 | /* $OpenBSD: wycheproof.go,v 1.189 2025/09/08 08:11:49 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2018,2023 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2018,2023 Joel Sing <jsing@openbsd.org> |
4 | * Copyright (c) 2018,2019,2022-2025 Theo Buehler <tb@openbsd.org> | 4 | * Copyright (c) 2018,2019,2022-2025 Theo Buehler <tb@openbsd.org> |
@@ -84,7 +84,6 @@ import ( | |||
84 | "math/big" | 84 | "math/big" |
85 | "os" | 85 | "os" |
86 | "path/filepath" | 86 | "path/filepath" |
87 | "regexp" | ||
88 | "runtime" | 87 | "runtime" |
89 | "strings" | 88 | "strings" |
90 | "sync" | 89 | "sync" |
@@ -2752,14 +2751,28 @@ func testGroupFromTestVector(wtv *wycheproofTestVectorsV1) (wycheproofTestGroupR | |||
2752 | variant := Normal | 2751 | variant := Normal |
2753 | 2752 | ||
2754 | switch wtv.Algorithm { | 2753 | switch wtv.Algorithm { |
2754 | case "A128CBC-HS256", "A192CBC-HS384", "A256CBC-HS512": | ||
2755 | return nil, Skip | ||
2756 | case "AEGIS128", "AEGIS128L", "AEGIS256": | ||
2757 | return nil, Skip | ||
2758 | case "AEAD-AES-SIV-CMAC": | ||
2759 | return nil, Skip | ||
2755 | case "AES-CBC-PKCS5": | 2760 | case "AES-CBC-PKCS5": |
2756 | return &wycheproofTestGroupAesCbcPkcs5{}, variant | 2761 | return &wycheproofTestGroupAesCbcPkcs5{}, variant |
2757 | case "AES-CCM", "AES-GCM": | 2762 | case "AES-CCM", "AES-GCM": |
2758 | return &wycheproofTestGroupAesAead{}, variant | 2763 | return &wycheproofTestGroupAesAead{}, variant |
2759 | case "AES-CMAC": | 2764 | case "AES-CMAC": |
2760 | return &wycheproofTestGroupAesCmac{}, variant | 2765 | return &wycheproofTestGroupAesCmac{}, variant |
2766 | case "AES-EAX", "AES-FF1", "AES-GCM-SIV", "AES-GMAC", "AES-KWP", "AES-SIV-CMAC", "AES-XTS": | ||
2767 | return nil, Skip | ||
2761 | case "AES-WRAP": | 2768 | case "AES-WRAP": |
2762 | return &wycheproofTestGroupKW{}, variant | 2769 | return &wycheproofTestGroupKW{}, variant |
2770 | case "ARIA-CBC-PKCS5", "ARIA-CCM", "ARIA-CMAC", "ARIA-GCM", "ARIA-KWP", "ARIA-WRAP": | ||
2771 | return nil, Skip | ||
2772 | case "ASCON128", "ASCON128A", "ASCON80PQ": | ||
2773 | return nil, Skip | ||
2774 | case "CAMELLIA-CBC-PKCS5", "CAMELLIA-CCM", "CAMELLIA-CMAC", "CAMELLIA-WRAP": | ||
2775 | return nil, Skip | ||
2763 | case "CHACHA20-POLY1305", "XCHACHA20-POLY1305": | 2776 | case "CHACHA20-POLY1305", "XCHACHA20-POLY1305": |
2764 | return &wycheproofTestGroupChaCha{}, variant | 2777 | return &wycheproofTestGroupChaCha{}, variant |
2765 | case "DSA": | 2778 | case "DSA": |
@@ -2776,8 +2789,14 @@ func testGroupFromTestVector(wtv *wycheproofTestVectorsV1) (wycheproofTestGroupR | |||
2776 | if wtv.Schema == "ecdh_ecpoint_test_schema_v1.json" { | 2789 | if wtv.Schema == "ecdh_ecpoint_test_schema_v1.json" { |
2777 | variant = EcPoint | 2790 | variant = EcPoint |
2778 | } | 2791 | } |
2792 | if wtv.Schema == "ecdh_pem_test_schema_v1.json" { | ||
2793 | variant = Skip | ||
2794 | } | ||
2779 | return &wycheproofTestGroupECDH{}, variant | 2795 | return &wycheproofTestGroupECDH{}, variant |
2780 | case "ECDSA": | 2796 | case "ECDSA": |
2797 | if wtv.Schema == "ecdsa_bitcoin_verify_schema.json" { | ||
2798 | variant = Skip | ||
2799 | } | ||
2781 | if wtv.Schema == "ecdsa_p1363_verify_schema_v1.json" { | 2800 | if wtv.Schema == "ecdsa_p1363_verify_schema_v1.json" { |
2782 | variant = P1363 | 2801 | variant = P1363 |
2783 | } | 2802 | } |
@@ -2788,6 +2807,21 @@ func testGroupFromTestVector(wtv *wycheproofTestVectorsV1) (wycheproofTestGroupR | |||
2788 | return &wycheproofTestGroupHkdf{}, variant | 2807 | return &wycheproofTestGroupHkdf{}, variant |
2789 | case "HMACSHA1", "HMACSHA224", "HMACSHA256", "HMACSHA384", "HMACSHA512", "HMACSHA512/224", "HMACSHA512/256", "HMACSHA3-224", "HMACSHA3-256", "HMACSHA3-384", "HMACSHA3-512": | 2808 | case "HMACSHA1", "HMACSHA224", "HMACSHA256", "HMACSHA384", "HMACSHA512", "HMACSHA512/224", "HMACSHA512/256", "HMACSHA3-224", "HMACSHA3-256", "HMACSHA3-384", "HMACSHA3-512": |
2790 | return &wycheproofTestGroupHmac{}, variant | 2809 | return &wycheproofTestGroupHmac{}, variant |
2810 | case "HMACSM3": | ||
2811 | return nil, Skip | ||
2812 | case "KMAC128", "KMAC256": | ||
2813 | return nil, Skip | ||
2814 | case "ML-DSA-44", "ML-DSA-65", "ML-DSA-87": | ||
2815 | return nil, Skip | ||
2816 | case "ML-KEM": | ||
2817 | return nil, Skip | ||
2818 | case "MORUS640", "MORUS1280": | ||
2819 | return nil, Skip | ||
2820 | case "PbeWithHmacSha1AndAes_128", "PbeWithHmacSha1AndAes_192", "PbeWithHmacSha1AndAes_256", "PbeWithHmacSha224AndAes_128", "PbeWithHmacSha224AndAes_192", "PbeWithHmacSha224AndAes_256", "PbeWithHmacSha256AndAes_128", "PbeWithHmacSha256AndAes_192", "PbeWithHmacSha256AndAes_256", "PbeWithHmacSha384AndAes_128", "PbeWithHmacSha384AndAes_192", "PbeWithHmacSha384AndAes_256", "PbeWithHmacSha512AndAes_128", "PbeWithHmacSha512AndAes_192", "PbeWithHmacSha512AndAes_256": | ||
2821 | return nil, Skip | ||
2822 | |||
2823 | case "PBKDF2-HMACSHA1", "PBKDF2-HMACSHA224", "PBKDF2-HMACSHA256", "PBKDF2-HMACSHA384", "PBKDF2-HMACSHA512": | ||
2824 | return nil, Skip | ||
2791 | case "PrimalityTest": | 2825 | case "PrimalityTest": |
2792 | return &wycheproofTestGroupPrimality{}, variant | 2826 | return &wycheproofTestGroupPrimality{}, variant |
2793 | case "RSAES-OAEP": | 2827 | case "RSAES-OAEP": |
@@ -2798,16 +2832,32 @@ func testGroupFromTestVector(wtv *wycheproofTestVectorsV1) (wycheproofTestGroupR | |||
2798 | return &wycheproofTestGroupRsassa{}, variant | 2832 | return &wycheproofTestGroupRsassa{}, variant |
2799 | case "RSASSA-PKCS1-v1_5", "RSASig": | 2833 | case "RSASSA-PKCS1-v1_5", "RSASig": |
2800 | return &wycheproofTestGroupRSA{}, variant | 2834 | return &wycheproofTestGroupRSA{}, variant |
2801 | case "XDH", "X25519": | 2835 | case "SEED-CCM", "SEED-GCM", "SEED-WRAP": |
2836 | return nil, Skip | ||
2837 | case "SipHash-1-3", "SipHash-2-4", "SipHash-4-8", "SipHashX-2-4", "SipHashX-4-8": | ||
2838 | return nil, Skip | ||
2839 | case "SM4-CCM", "SM4-GCM": | ||
2840 | return nil, Skip | ||
2841 | case "VMAC-AES": | ||
2842 | return nil, Skip | ||
2843 | case "XDH": | ||
2844 | switch wtv.Schema { | ||
2845 | case "xdh_asn_comp_schema_v1.json", "xdh_jwk_comp_schema_v1.json", "xdh_pem_comp_schema_v1.json": | ||
2846 | variant = Skip | ||
2847 | case "xdh_comp_schema_v1.json": | ||
2848 | variant = Normal | ||
2849 | } | ||
2802 | return &wycheproofTestGroupX25519{}, variant | 2850 | return &wycheproofTestGroupX25519{}, variant |
2803 | default: | 2851 | default: |
2804 | return nil, Skip | 2852 | // XXX - JOSE tests don't set an Algorithm... |
2853 | if strings.HasPrefix(wtv.Schema, "json_web_") { | ||
2854 | return nil, Skip | ||
2855 | } | ||
2856 | return nil, Normal | ||
2805 | } | 2857 | } |
2806 | } | 2858 | } |
2807 | 2859 | ||
2808 | func runTestVectors(path string) bool { | 2860 | func runTestVectors(path string) bool { |
2809 | var algorithm string | ||
2810 | var testGroups []json.RawMessage | ||
2811 | b, err := ioutil.ReadFile(path) | 2861 | b, err := ioutil.ReadFile(path) |
2812 | if err != nil { | 2862 | if err != nil { |
2813 | log.Fatalf("Failed to read test vectors: %v", err) | 2863 | log.Fatalf("Failed to read test vectors: %v", err) |
@@ -2816,25 +2866,26 @@ func runTestVectors(path string) bool { | |||
2816 | if err := json.Unmarshal(b, wtv); err != nil { | 2866 | if err := json.Unmarshal(b, wtv); err != nil { |
2817 | log.Fatalf("Failed to unmarshal JSON: %v", err) | 2867 | log.Fatalf("Failed to unmarshal JSON: %v", err) |
2818 | } | 2868 | } |
2819 | algorithm = wtv.Algorithm | ||
2820 | testGroups = wtv.TestGroups | ||
2821 | fmt.Printf("Loaded Wycheproof test vectors for %v with %d tests from %q\n", wtv.Algorithm, wtv.NumberOfTests, filepath.Base(path)) | 2869 | fmt.Printf("Loaded Wycheproof test vectors for %v with %d tests from %q\n", wtv.Algorithm, wtv.NumberOfTests, filepath.Base(path)) |
2822 | 2870 | ||
2823 | success := true | 2871 | success := true |
2824 | for _, tg := range testGroups { | 2872 | for _, tg := range wtv.TestGroups { |
2825 | wtg, variant := testGroupFromTestVector(wtv) | 2873 | wtg, variant := testGroupFromTestVector(wtv) |
2874 | if variant == Skip { | ||
2875 | fmt.Printf("INFO: Skipping tests from \"%s\"\n", filepath.Base(path)) | ||
2876 | return true | ||
2877 | } | ||
2826 | if wtg == nil { | 2878 | if wtg == nil { |
2827 | log.Printf("INFO: Unknown test vector algorithm %q", algorithm) | 2879 | log.Fatalf("INFO: Unknown test vector algorithm %qin \"%s\"", wtv.Algorithm, filepath.Base(path)) |
2828 | return false | ||
2829 | } | 2880 | } |
2830 | if err := json.Unmarshal(tg, wtg); err != nil { | 2881 | if err := json.Unmarshal(tg, wtg); err != nil { |
2831 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) | 2882 | log.Fatalf("Failed to unmarshal test groups JSON: %v", err) |
2832 | } | 2883 | } |
2833 | testc.runTest(func() bool { | 2884 | testc.runTest(func() bool { |
2834 | return wtg.run(algorithm, variant) | 2885 | return wtg.run(wtv.Algorithm, variant) |
2835 | }) | 2886 | }) |
2836 | } | 2887 | } |
2837 | for _ = range testGroups { | 2888 | for _ = range wtv.TestGroups { |
2838 | result := <-testc.resultCh | 2889 | result := <-testc.resultCh |
2839 | if !result { | 2890 | if !result { |
2840 | success = false | 2891 | success = false |
@@ -2886,36 +2937,6 @@ func main() { | |||
2886 | os.Exit(0) | 2937 | os.Exit(0) |
2887 | } | 2938 | } |
2888 | 2939 | ||
2889 | tests := []struct { | ||
2890 | name string | ||
2891 | pattern string | ||
2892 | variant testVariant | ||
2893 | }{ | ||
2894 | {"AES", "aes_[cg]*[^xv]_test.json", Normal}, // Skip AES-EAX, AES-GCM-SIV and AES-SIV-CMAC. | ||
2895 | {"AES-WRAP", "aes_wrap_test.json", Normal}, | ||
2896 | {"ChaCha20-Poly1305", "chacha20_poly1305_test.json", Normal}, | ||
2897 | {"DSA", "dsa_*test.json", Normal}, | ||
2898 | {"DSA", "dsa_*_p1363_test.json", P1363}, | ||
2899 | {"EcCurveTest", "ec_prime_order_curves_test.json", Normal}, | ||
2900 | {"ECDH", "ecdh_[^w_]*_test.json", Normal}, | ||
2901 | {"ECDH EcPoint", "ecdh_*_ecpoint_test.json", EcPoint}, | ||
2902 | {"ECDH webcrypto", "ecdh_*_webcrypto_test.json", Webcrypto}, | ||
2903 | {"ECDSA", "ecdsa_[^w]*test.json", Normal}, | ||
2904 | {"ECDSA P1363", "ecdsa_*_sha[1-9][1-9][1-9]_p1363_test.json", P1363}, | ||
2905 | {"ECDSA shake", "ecdsa_*_shake*_test.json", Skip}, | ||
2906 | {"EDDSA", "ed25519_test.json", Normal}, | ||
2907 | {"ED448", "ed448_test.json", Skip}, | ||
2908 | {"HKDF", "hkdf_sha*_test.json", Normal}, | ||
2909 | {"HMAC", "hmac_sha*_test.json", Normal}, | ||
2910 | {"Primality test", "primality_test.json", Normal}, | ||
2911 | {"RSA", "rsa_*test.json", Normal}, | ||
2912 | {"X25519", "x25519_test.json", Normal}, | ||
2913 | {"X25519 ASN", "x25519_asn_test.json", Skip}, | ||
2914 | {"X25519 JWK", "x25519_jwk_test.json", Skip}, | ||
2915 | {"X25519 PEM", "x25519_pem_test.json", Skip}, | ||
2916 | {"XCHACHA20-POLY1305", "xchacha20_poly1305_test.json", Normal}, | ||
2917 | } | ||
2918 | |||
2919 | success := true | 2940 | success := true |
2920 | 2941 | ||
2921 | var wg sync.WaitGroup | 2942 | var wg sync.WaitGroup |
@@ -2928,33 +2949,25 @@ func main() { | |||
2928 | 2949 | ||
2929 | testc = newTestCoordinator() | 2950 | testc = newTestCoordinator() |
2930 | 2951 | ||
2931 | skipNormal := regexp.MustCompile(`_(ecpoint|webcrypto|pem|bitcoin|shake\d{3}|gmac|p1363|sect\d{3}[rk]1|secp(160|192))_`) | 2952 | tvs, err := filepath.Glob(filepath.Join(path, "*.json")) |
2932 | 2953 | if err != nil { | |
2933 | for _, test := range tests { | 2954 | log.Fatalf("Failed to glob test vectors: %v", err) |
2934 | tvs, err := filepath.Glob(filepath.Join(path, test.pattern)) | 2955 | } |
2935 | if err != nil { | 2956 | if len(tvs) == 0 { |
2936 | log.Fatalf("Failed to glob %v test vectors: %v", test.name, err) | 2957 | log.Fatalf("Failed to find test vectors at %q\n", path) |
2937 | } | 2958 | } |
2938 | if len(tvs) == 0 { | 2959 | for _, tv := range tvs { |
2939 | log.Fatalf("Failed to find %v test vectors at %q\n", test.name, path) | 2960 | wg.Add(1) |
2940 | } | 2961 | <-vectorsRateLimitCh |
2941 | for _, tv := range tvs { | 2962 | go func(tv string) { |
2942 | if test.variant == Skip || (test.variant == Normal && skipNormal.Match([]byte(tv))) { | 2963 | select { |
2943 | fmt.Printf("INFO: Skipping tests from \"%s\"\n", strings.TrimPrefix(tv, path+"/")) | 2964 | case resultCh <- runTestVectors(tv): |
2944 | continue | 2965 | default: |
2966 | log.Fatal("result channel is full") | ||
2945 | } | 2967 | } |
2946 | wg.Add(1) | 2968 | vectorsRateLimitCh <- true |
2947 | <-vectorsRateLimitCh | 2969 | wg.Done() |
2948 | go func(tv string) { | 2970 | }(tv) |
2949 | select { | ||
2950 | case resultCh <- runTestVectors(tv): | ||
2951 | default: | ||
2952 | log.Fatal("result channel is full") | ||
2953 | } | ||
2954 | vectorsRateLimitCh <- true | ||
2955 | wg.Done() | ||
2956 | }(tv) | ||
2957 | } | ||
2958 | } | 2971 | } |
2959 | 2972 | ||
2960 | wg.Wait() | 2973 | wg.Wait() |