diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile new file mode 100644 index 0000000..e9e9ad2 --- /dev/null +++ b/.clusterfuzzlite/Dockerfile @@ -0,0 +1,5 @@ +FROM gcr.io/oss-fuzz-base/base-builder-go +RUN git clone --depth 1 https://github.com/bytemare/opaque.git +COPY . $SRC/opaque +WORKDIR $SRC/opaque +COPY ./.clusterfuzzlite/build.sh $SRC/ \ No newline at end of file diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh new file mode 100644 index 0000000..8c97745 --- /dev/null +++ b/.clusterfuzzlite/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash -eu + +set -ex + +# compile_go_fuzzer github.com/bytemare/opaque FuzzConfiguration Fuzz_Configuration fuzz +# compile_go_fuzzer github.com/bytemare/opaque FuzzDeserializeRegistrationRequest Fuzz_DeserializeRegistrationRequest fuzz +# compile_go_fuzzer github.com/bytemare/opaque FuzzDeserializeRegistrationResponse Fuzz_DeserializeRegistrationResponse fuzz +# compile_go_fuzzer github.com/bytemare/opaque FuzzDeserializeRegistrationRecord Fuzz_DeserializeRegistrationRecord fuzz +# compile_go_fuzzer github.com/bytemare/opaque FuzzDeserializeKE1 Fuzz_DeserializeKE1 fuzz +# compile_go_fuzzer github.com/bytemare/opaque FuzzDeserializeKE2 Fuzz_DeserializeKE2 fuzz +# compile_go_fuzzer github.com/bytemare/opaque FuzzDeserializeKE3 Fuzz_DeserializeKE3 fuzz +compile_go_fuzzer github.com/bytemare/opaque/opaque_test FuzzKE3 Fuzz_DeserializeKE3 fuzz diff --git a/.clusterfuzzlite/project.yaml b/.clusterfuzzlite/project.yaml new file mode 100644 index 0000000..4767f8a --- /dev/null +++ b/.clusterfuzzlite/project.yaml @@ -0,0 +1,10 @@ +homepage: "https://github.com/bytemare/opaque" +language: go +sanitizers: + - address + - undefined + - memory +architectures: + - x86_64 + - i386 +main_repo: 'https://github.com/bytemare/opaque.git' \ No newline at end of file diff --git a/.github/Makefile b/.github/Makefile index 378fc0b..872201e 100644 --- a/.github/Makefile +++ b/.github/Makefile @@ -39,7 +39,7 @@ lint: fmt license .PHONY: test test: @echo "Running all tests ..." - @go test -v -vet=all ../tests + @go test -v -vet=all ../... .PHONY: vectors vectors: diff --git a/.github/workflows/cflite_batch.yml b/.github/workflows/cflite_batch.yml new file mode 100644 index 0000000..21f32dc --- /dev/null +++ b/.github/workflows/cflite_batch.yml @@ -0,0 +1,34 @@ +name: ClusterFuzzLite batch fuzzing +on: + schedule: + - cron: '0 0/6 * * *' # Every 6th hour. Change this to whatever is suitable. +permissions: read-all +jobs: + BatchFuzzing: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] # Override this with the sanitizers you want. + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: go # Change this to the language you are fuzzing. + sanitizer: ${{ matrix.sanitizer }} + - name: Run Fuzzers (${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 3600 + mode: 'batch' + sanitizer: ${{ matrix.sanitizer }} + output-sarif: true + # Optional but recommended: For storing certain artifacts from fuzzing. + # See later section on "Git repo for storage". + storage-repo: https://${{ secrets.FUZZ_STORAGE_REPO_TOKEN }}@github.com/bytemare/fuzzing.git + storage-repo-branch: main # Optional. Defaults to "main" + storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + parallel-fuzzing: true diff --git a/.github/workflows/cflite_build.yml b/.github/workflows/cflite_build.yml new file mode 100644 index 0000000..8ed55e5 --- /dev/null +++ b/.github/workflows/cflite_build.yml @@ -0,0 +1,24 @@ +name: ClusterFuzzLite continuous builds +on: + push: + branches: + - main # Use your actual default branch here. +permissions: read-all +jobs: + Build: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] # Override this with the sanitizers you want. + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: go # Change this to the language you are fuzzing. + sanitizer: ${{ matrix.sanitizer }} + upload-build: true diff --git a/.github/workflows/cflite_cron.yml b/.github/workflows/cflite_cron.yml new file mode 100644 index 0000000..82aa199 --- /dev/null +++ b/.github/workflows/cflite_cron.yml @@ -0,0 +1,49 @@ +name: ClusterFuzzLite cron tasks +on: + schedule: + - cron: '0 0 * * *' # Once a day at midnight. +permissions: read-all +jobs: + Pruning: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: go # Change this to the language you are fuzzing + - name: Run Fuzzers + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 600 + mode: 'prune' + output-sarif: true + # Optional but recommended. + # See later section on "Git repo for storage". + storage-repo: https://${{ secrets.FUZZ_STORAGE_REPO_TOKEN }}@github.com/bytemare/fuzzing.git + storage-repo-branch: main # Optional. Defaults to "main" + storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + Coverage: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: go # Change this to the language you are fuzzing. + sanitizer: coverage + - name: Run Fuzzers + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 600 + mode: 'coverage' + sanitizer: 'coverage' + # Optional but recommended. + # See later section on "Git repo for storage". + storage-repo: https://${{ secrets.FUZZ_STORAGE_REPO_TOKEN }}@github.com/bytemare/fuzzing.git + storage-repo-branch: main # Optional. Defaults to "main" + storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". \ No newline at end of file diff --git a/.github/workflows/cflite_pr.yml b/.github/workflows/cflite_pr.yml new file mode 100644 index 0000000..aaa80d9 --- /dev/null +++ b/.github/workflows/cflite_pr.yml @@ -0,0 +1,46 @@ +name: ClusterFuzzLite PR fuzzing +on: + pull_request: + paths: + - '**' +permissions: read-all +jobs: + PR: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + sanitizer: [address, undefined, memory] # Override this with the sanitizers you want. + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: go # Change this to the language you are fuzzing. + github-token: ${{ secrets.GITHUB_TOKEN }} + sanitizer: ${{ matrix.sanitizer }} + # Optional but recommended: used to only run fuzzers that are affected + # by the PR. + # See later section on "Git repo for storage". + # storage-repo: https://${{ secrets.FUZZ_STORAGE_REPO_TOKEN }}@github.com/bytemare/fuzzing.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + - name: Run Fuzzers (${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 600 + mode: 'code-change' + sanitizer: ${{ matrix.sanitizer }} + output-sarif: true + # Optional but recommended: used to download the corpus produced by + # batch fuzzing. + # See later section on "Git repo for storage". + storage-repo: https://${{ secrets.FUZZ_STORAGE_REPO_TOKEN }}@github.com/bytemare/fuzzing.git + storage-repo-branch: main # Optional. Defaults to "main" + storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + parallel-fuzzing: true diff --git a/examples_test.go b/examples_test.go index f4547bd..f32c4b4 100644 --- a/examples_test.go +++ b/examples_test.go @@ -276,7 +276,7 @@ func Example_registration() { fmt.Println("OPAQUE registration is easy!") } - // Output: OPAQUE server values initialized. + // Output: OPAQUE server initialized. // OPAQUE registration is easy! } @@ -384,7 +384,7 @@ func Example_loginKeyExchange() { } fmt.Println("OPAQUE is much awesome!") - // Output: OPAQUE server values initialized. + // Output: OPAQUE server initialized. // OPAQUE registration is easy! // OPAQUE is much awesome! } @@ -450,6 +450,6 @@ func Example_fakeResponse() { fmt.Println("Thwarting OPAQUE client enumeration is easy!") } - // Output: OPAQUE server values initialized. + // Output: OPAQUE server initialized. // Thwarting OPAQUE client enumeration is easy! } diff --git a/tests/fuzz_test.go b/fuzz_test.go similarity index 66% rename from tests/fuzz_test.go rename to fuzz_test.go index 2ffe1cf..d634164 100644 --- a/tests/fuzz_test.go +++ b/fuzz_test.go @@ -10,11 +10,8 @@ package opaque_test import ( "crypto" - "encoding/json" "errors" "fmt" - "log" - "os" "strings" "testing" @@ -26,21 +23,27 @@ import ( "github.com/bytemare/opaque/internal/oprf" ) -const ( - fmtGotValidInput = "got %q but input is valid" -) +const fmtGotValidInput = "got %q but input is valid" + +type fuzzConfError struct { + error error + value interface{} + isAvailable bool +} // skipErrorOnCondition skips the test if we find the expected error in err and cond if false. -func skipErrorOnCondition(t *testing.T, expected, err error, cond bool, val interface{}) { - if strings.Contains(expected.Error(), err.Error()) { - if cond { - t.Fatalf("got %q but input is valid: %q", err, val) +func skipErrorOnCondition(t *testing.T, expected error, ce *fuzzConfError) error { + if strings.Contains(expected.Error(), ce.error.Error()) { + if ce.isAvailable { + return fmt.Errorf("got %q but input is valid: %q", ce.error, ce.value) } t.Skip() } + + return nil } -func fuzzTestConfigurationError(t *testing.T, c *opaque.Configuration, err error) { +func fuzzTestConfigurationError(t *testing.T, c *opaque.Configuration, err error) error { // Errors tested for var ( errInvalidKDFid = errors.New("invalid KDF id") @@ -51,133 +54,162 @@ func fuzzTestConfigurationError(t *testing.T, c *opaque.Configuration, err error errInvalidAKEid = errors.New("invalid AKE group id") ) - skipErrorOnCondition(t, err, errInvalidKDFid, hash.Hashing(c.KDF).Available(), c.KDF) - skipErrorOnCondition(t, err, errInvalidMACid, hash.Hashing(c.MAC).Available(), c.MAC) - skipErrorOnCondition(t, err, errInvalidHASHid, hash.Hashing(c.Hash).Available(), c.Hash) - skipErrorOnCondition(t, err, errInvalidKSFid, c.KSF.Available(), c.KSF) - skipErrorOnCondition(t, err, errInvalidOPRFid, c.OPRF.OPRF().Available(), c.OPRF) - skipErrorOnCondition(t, err, errInvalidAKEid, c.AKE.Group().Available(), c.AKE) + errorTests := []*fuzzConfError{ + {errInvalidKDFid, c.KDF, hash.Hashing(c.KDF).Available()}, + {errInvalidMACid, c.MAC, hash.Hashing(c.MAC).Available()}, + {errInvalidHASHid, c.Hash, hash.Hashing(c.Hash).Available()}, + {errInvalidKSFid, c.KSF, c.KSF == 0 && c.KSF.Available()}, + {errInvalidOPRFid, c.OPRF, c.OPRF.Available() && c.OPRF.OPRF().Available()}, + {errInvalidAKEid, c.AKE, c.AKE.Available() && c.AKE.Group().Available()}, + } + + for _, test := range errorTests { + if e := skipErrorOnCondition(t, err, test); e != nil { + return e + } + } - t.Fatalf("Unrecognized error: %q", err) + return fmt.Errorf("unrecognized error: %w", err) } -func fuzzClientConfiguration(t *testing.T, c *opaque.Configuration) *opaque.Client { +func DoFuzzClientConfiguration(t *testing.T, c *opaque.Configuration) (*opaque.Client, error) { client, err := c.Client() if err != nil { - fuzzTestConfigurationError(t, c, err) + if err = fuzzTestConfigurationError(t, c, err); err != nil { + return nil, err + } } if client == nil { t.Fatal("server is nil") } - return client + return client, nil } -func fuzzServerConfiguration(t *testing.T, c *opaque.Configuration) *opaque.Server { +func DoFuzzServerConfiguration(t *testing.T, c *opaque.Configuration) (*opaque.Server, error) { server, err := c.Server() if err != nil { - fuzzTestConfigurationError(t, c, err) + if err = fuzzTestConfigurationError(t, c, err); err != nil { + return nil, err + } } if server == nil { t.Fatal("server is nil") } - return server + return server, nil } -func fuzzLoadVectors(path string) ([]*vector, error) { - contents, err := os.ReadFile(path) - if err != nil { - return nil, fmt.Errorf("no vectors to read: %v", err) - } - - var v []*vector - err = json.Unmarshal(contents, &v) - if err != nil { - return nil, fmt.Errorf("no vectors to read: %v", err) - } - - return v, nil -} +//func DoFuzzLoadVectors(path string) ([]*vector, error) { +// contents, err := os.ReadFile(path) +// if err != nil { +// return nil, fmt.Errorf("no vectors to read: %v", err) +// } +// +// var v []*vector +// err = json.Unmarshal(contents, &v) +// if err != nil { +// return nil, fmt.Errorf("no vectors to read: %v", err) +// } +// +// return v, nil +//} func FuzzConfiguration(f *testing.F) { // seed corpus - loadVectorSeedCorpus(f, "") + // loadVectorSeedCorpus(f, "") f.Fuzz(func(t *testing.T, ke1, context []byte, kdf, mac, h uint, o []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, o, ksfID, ake) - _ = fuzzServerConfiguration(t, c) - _ = fuzzClientConfiguration(t, c) - }) -} - -func loadVectorSeedCorpus(f *testing.F, stage string) { - // seed corpus - vectors, err := fuzzLoadVectors("vectors.json") - if err != nil { - log.Fatal(err) - } - for _, v := range vectors { - if v.Config.Group == "curve25519" { - continue + if _, err := DoFuzzServerConfiguration(t, c); err != nil { + t.Fatal(err) } - var input ByteToHex - switch stage { - case "": - input = nil - case "RegistrationRequest": - input = v.Outputs.RegistrationRequest - case "RegistrationResponse": - input = v.Outputs.RegistrationResponse - case "RegistrationRecord": - input = v.Outputs.RegistrationRecord - case "KE1": - input = v.Outputs.KE1 - case "KE2": - input = v.Outputs.KE2 - case "KE3": - input = v.Outputs.KE3 - default: - panic(nil) + if _, err := DoFuzzClientConfiguration(t, c); err != nil { + t.Fatal(err) } + }) +} - f.Add([]byte(input), - []byte(v.Config.Context), - uint(kdfToHash(v.Config.KDF)), - uint(macToHash(v.Config.MAC)), - uint(hashToHash(v.Config.Hash)), - []byte(v.Config.OPRF), - byte(ksfToKSF(v.Config.KSF)), - byte(groupToGroup(v.Config.Group)), - ) +//func //loadVectorSeedCorpus(f *testing.F, stage string) { +// // seed corpus +// vectors, err := DoFuzzLoadVectors("vectors.json") +// if err != nil { +// log.Fatal(err) +// } +// +// for _, v := range vectors { +// if v.Config.Group == "curve25519" { +// continue +// } +// +// var input ByteToHex +// switch stage { +// case "": +// input = nil +// case "RegistrationRequest": +// input = v.Outputs.RegistrationRequest +// case "RegistrationResponse": +// input = v.Outputs.RegistrationResponse +// case "RegistrationRecord": +// input = v.Outputs.RegistrationRecord +// case "KE1": +// input = v.Outputs.KE1 +// case "KE2": +// input = v.Outputs.KE2 +// case "KE3": +// input = v.Outputs.KE3 +// default: +// panic(nil) +// } +// +// f.Add([]byte(input), +// []byte(v.Config.Context), +// uint(kdfToHash(v.Config.KDF)), +// uint(macToHash(v.Config.MAC)), +// uint(hashToHash(v.Config.Hash)), +// []byte(v.Config.OPRF), +// byte(ksfToKSF(v.Config.KSF)), +// byte(groupToGroup(v.Config.Group)), +// ) +// } +// +// // previous crashers +// f.Add([]byte("0"), []byte(""), uint(7), uint(37), uint(7), []byte{'\x05'}, byte('\x02'), byte('\x05')) +// f.Add([]byte("0"), []byte("0"), uint(13), uint(5), uint(5), []byte{'\x03'}, byte('\r'), byte('\x03')) +// f.Add([]byte("0"), []byte("0"), uint(13), uint(5), uint(5), []byte{'\a'}, byte('\x04'), byte('\x03')) +// f.Add( +// []byte("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), +// []byte("0"), +// uint(7), +// uint(7), +// uint(7), +// []byte{'\x01'}, +// byte('\x03'), +// byte('\x01'), +// ) +// f.Add( +// []byte("00000000000000000000000000000000"), +// []byte("0"), +// uint(7), +// uint(7), +// uint(7), +// []byte{'\x01'}, +// byte('\x03'), +// byte('\x06'), +// ) +//} + +func oprfToGroup(oprf oprf.Identifier) opaque.Group { + switch oprf { + case "ristretto255-SHA512": + return opaque.RistrettoSha512 + case "P256-SHA256": + return opaque.P256Sha256 + default: + return 0 } - - // previous crashers - f.Add([]byte("0"), []byte(""), uint(7), uint(37), uint(7), []byte{'\x05'}, byte('\x02'), byte('\x05')) - f.Add([]byte("0"), []byte("0"), uint(13), uint(5), uint(5), []byte{'\x03'}, byte('\r'), byte('\x03')) - f.Add([]byte("0"), []byte("0"), uint(13), uint(5), uint(5), []byte{'\a'}, byte('\x04'), byte('\x03')) - f.Add( - []byte("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), - []byte("0"), - uint(7), - uint(7), - uint(7), - []byte{'\x01'}, - byte('\x03'), - byte('\x01'), - ) - f.Add( - []byte("00000000000000000000000000000000"), - []byte("0"), - uint(7), - uint(7), - uint(7), - []byte{'\x01'}, - byte('\x03'), - byte('\x06'), - ) } func inputToConfig(context []byte, kdf, mac, h uint, o []byte, ksfID, ake byte) *opaque.Configuration { @@ -199,7 +231,7 @@ func FuzzDeserializeRegistrationRequest(f *testing.F) { errInvalidBlindedData = errors.New("blinded data is an invalid point") ) - loadVectorSeedCorpus(f, "RegistrationRequest") + // loadVectorSeedCorpus(f, "RegistrationRequest") f.Fuzz(func(t *testing.T, r1, context []byte, kdf, mac, h uint, oprf []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, oprf, ksfID, ake) @@ -233,7 +265,7 @@ func FuzzDeserializeRegistrationResponse(f *testing.F) { errInvalidServerPK = errors.New("invalid server public key") ) - loadVectorSeedCorpus(f, "RegistrationResponse") + // loadVectorSeedCorpus(f, "RegistrationResponse") f.Fuzz(func(t *testing.T, r2, context []byte, kdf, mac, h uint, oprf []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, oprf, ksfID, ake) @@ -273,7 +305,7 @@ func FuzzDeserializeRegistrationRecord(f *testing.F) { errInvalidClientPK = errors.New("invalid client public key") ) - loadVectorSeedCorpus(f, "RegistrationRecord") + // loadVectorSeedCorpus(f, "RegistrationRecord") f.Fuzz(func(t *testing.T, r3, context []byte, kdf, mac, h uint, oprf []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, oprf, ksfID, ake) @@ -309,7 +341,7 @@ func FuzzDeserializeKE1(f *testing.F) { errInvalidClientEPK = errors.New("invalid ephemeral client public key") ) - loadVectorSeedCorpus(f, "KE1") + // loadVectorSeedCorpus(f, "KE1") f.Fuzz(func(t *testing.T, ke1, context []byte, kdf, mac, h uint, oprf []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, oprf, ksfID, ake) @@ -375,7 +407,7 @@ func FuzzDeserializeKE2(f *testing.F) { errInvalidServerEPK = errors.New("invalid ephemeral server public key") ) - loadVectorSeedCorpus(f, "KE2") + // loadVectorSeedCorpus(f, "KE2") f.Fuzz(func(t *testing.T, ke2, context []byte, kdf, mac, h uint, oprf []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, oprf, ksfID, ake) @@ -415,7 +447,7 @@ func FuzzDeserializeKE3(f *testing.F) { // Error tested for errInvalidMessageLength := errors.New("invalid message length for the configuration") - loadVectorSeedCorpus(f, "KE3") + // loadVectorSeedCorpus(f, "KE3") f.Fuzz(func(t *testing.T, ke3, context []byte, kdf, mac, h uint, oprf []byte, ksfID, ake byte) { c := inputToConfig(context, kdf, mac, h, oprf, ksfID, ake) @@ -435,3 +467,25 @@ func FuzzDeserializeKE3(f *testing.F) { } }) } + +func FuzzKE3(data []byte) int { + // Error tested for + errInvalidMessageLength := errors.New("invalid message length for the configuration") + + server, err := opaque.NewServer(nil) + if err != nil { + fmt.Println(err) + return 0 + } + + _, err = server.Deserialize.KE3(data) + if err != nil { + conf := server.GetConf() + maxMessageLength := conf.MAC.Size() + + if strings.Contains(err.Error(), errInvalidMessageLength.Error()) && len(data) == maxMessageLength { + fmt.Printf(fmtGotValidInput+"\n", errInvalidMessageLength) + return 0 + } + } +} diff --git a/tests/doc.go b/tests/doc.go new file mode 100644 index 0000000..02e2e09 --- /dev/null +++ b/tests/doc.go @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (C) 2020-2022 Daniel Bourdrez. All Rights Reserved. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree or at +// https://spdx.org/licenses/MIT.html + +package opaque diff --git a/tests/testdata/fuzz/FuzzConfiguration/f3f7abd74e23d56a b/tests/testdata/fuzz/FuzzConfiguration/f3f7abd74e23d56a new file mode 100644 index 0000000..bdd81a2 --- /dev/null +++ b/tests/testdata/fuzz/FuzzConfiguration/f3f7abd74e23d56a @@ -0,0 +1,9 @@ +go test fuzz v1 +[]byte("") +[]byte("0") +uint(25) +uint(82) +uint(5) +[]byte("P256-SHA256") +byte('-') +byte('\x06')