src/crypto/internal/cryptotest/wycheproof/_schema/go.mod | 2 ++ src/crypto/internal/cryptotest/wycheproof/_schema/go.sum | 4 ++-- src/crypto/internal/cryptotest/wycheproof/schema.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/crypto/mldsa/mldsa_wycheproof_test.go | 47 +++++------------------------------------------ src/net/http/internal/http2/transport.go | 8 ++++++++ src/net/http/internal/http2/transport_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++- test/codegen/simd.go | 8 ++++---- diff --git a/src/crypto/internal/cryptotest/wycheproof/_schema/go.mod b/src/crypto/internal/cryptotest/wycheproof/_schema/go.mod index a94ecb8a9d5af968e93079a84130e982a2c55679..1253c1c5a94eb1fe0c7b3414e0892c3d35f01166 100644 --- a/src/crypto/internal/cryptotest/wycheproof/_schema/go.mod +++ b/src/crypto/internal/cryptotest/wycheproof/_schema/go.mod @@ -15,3 +15,5 @@ github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/sanity-io/litter v1.5.8 // indirect github.com/sosodev/duration v1.4.0 // indirect ) + +replace github.com/atombender/go-jsonschema => github.com/filippo-claude/go-jsonschema v0.23.2-0.20260625215234-f867483bec31 diff --git a/src/crypto/internal/cryptotest/wycheproof/_schema/go.sum b/src/crypto/internal/cryptotest/wycheproof/_schema/go.sum index 06b458e6434e890b3190a0e0d66d14c1fde2abe7..bc5fe4eb9e0b96f2deca0321da9d26dad9c00a51 100644 --- a/src/crypto/internal/cryptotest/wycheproof/_schema/go.sum +++ b/src/crypto/internal/cryptotest/wycheproof/_schema/go.sum @@ -1,12 +1,12 @@ dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/atombender/go-jsonschema v0.23.1 h1:hpj94ehS+gpVvd1NJSTE0BMtWIpab06ObCz57rwo37c= -github.com/atombender/go-jsonschema v0.23.1/go.mod h1:4SrgNrwGKijxhewvpPQ8HKEbin5Q2N4Tk+pFKW77HEk= github.com/c2sp/wycheproof v0.0.0-20260606153636-6d7cccd0fcb1 h1:veaGluF2y7kZnV/owZzY3FuOZWZQdzqnIcJsbJpFV7A= github.com/c2sp/wycheproof v0.0.0-20260606153636-6d7cccd0fcb1/go.mod h1:/5JsOpi3fKmnnig5BQ2mz49TNtnrD308VfTVHcbr5x4= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/filippo-claude/go-jsonschema v0.23.2-0.20260625215234-f867483bec31 h1:c2W1mlsq9K/W+GPQWycHmGxTq4/RkWgDHOY99K+rtaw= +github.com/filippo-claude/go-jsonschema v0.23.2-0.20260625215234-f867483bec31/go.mod h1:4SrgNrwGKijxhewvpPQ8HKEbin5Q2N4Tk+pFKW77HEk= github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= diff --git a/src/crypto/internal/cryptotest/wycheproof/schema.go b/src/crypto/internal/cryptotest/wycheproof/schema.go index b0a54590765558e499d6e9eb148cc4198e3828c5..50c655f6fe032e8ce8c0ae9e64b50b910fa422b6 100644 --- a/src/crypto/internal/cryptotest/wycheproof/schema.go +++ b/src/crypto/internal/cryptotest/wycheproof/schema.go @@ -6170,7 +6170,67 @@ *j = MlDsaSignTestGroup(plain) return nil } -type MlDsaSignTestVector interface{} +type MlDsaSignTestVector struct { + // A brief description of the test case + Comment string `json:"comment"` + + // [optional] The additional context string (if omitted, the context input is + // empty) + Ctx *string `json:"ctx,omitempty,omitzero"` + + // A list of flags + Flags []string `json:"flags"` + + // [optional] The message to sign (if omitted, mu is provided to use with + // Sign_internal) + Msg *string `json:"msg,omitempty,omitzero"` + + // [optional] The 64-byte μ value (omitted in case of expected failure) + Mu *string `json:"mu,omitempty,omitzero"` + + // Result corresponds to the JSON schema field "result". + Result Result `json:"result"` + + // [optional] The 32-byte random value (if omitted, implicitly all zeroes for + // deterministic signing) + Rnd *string `json:"rnd,omitempty,omitzero"` + + // The encoded signature (empty in case of expected failure) + Sig string `json:"sig"` + + // Identifier of the test case + TcId int `json:"tcId"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *MlDsaSignTestVector) UnmarshalJSON(value []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(value, &raw); err != nil { + return err + } + if _, ok := raw["comment"]; raw != nil && !ok { + return fmt.Errorf("field comment in MlDsaSignTestVector: required") + } + if _, ok := raw["flags"]; raw != nil && !ok { + return fmt.Errorf("field flags in MlDsaSignTestVector: required") + } + if _, ok := raw["result"]; raw != nil && !ok { + return fmt.Errorf("field result in MlDsaSignTestVector: required") + } + if _, ok := raw["sig"]; raw != nil && !ok { + return fmt.Errorf("field sig in MlDsaSignTestVector: required") + } + if _, ok := raw["tcId"]; raw != nil && !ok { + return fmt.Errorf("field tcId in MlDsaSignTestVector: required") + } + type Plain MlDsaSignTestVector + var plain Plain + if err := json.Unmarshal(value, &plain); err != nil { + return err + } + *j = MlDsaSignTestVector(plain) + return nil +} type MlDsaVerifyTestGroup struct { // Encoded ML-DSA public key diff --git a/src/crypto/mldsa/mldsa_wycheproof_test.go b/src/crypto/mldsa/mldsa_wycheproof_test.go index 8abef0474551e49d037d553d08adad56d20d1aef..9a5bcd3ae488d8dd45336923f09a571e44e3a22c 100644 --- a/src/crypto/mldsa/mldsa_wycheproof_test.go +++ b/src/crypto/mldsa/mldsa_wycheproof_test.go @@ -12,7 +12,6 @@ "crypto" "crypto/internal/cryptotest/wycheproof" internalmldsa "crypto/internal/fips140/mldsa" "crypto/mldsa" - "encoding/json" "slices" "testing" ) @@ -95,9 +94,7 @@ if pk, ok := tg.PublicKey.(string); ok { expectedPublicKey = wycheproof.MustDecodeHex(pk) } - for _, raw := range tg.Tests { - tv := decodeMLDSASignTestVector(t, raw) - + for _, tv := range tg.Tests { t.Run(wycheproof.TestName(file, tv), func(t *testing.T) { t.Parallel() @@ -128,7 +125,7 @@ } } } -func runSignTest(t *testing.T, priv *mldsa.PrivateKey, tv mldsaSignTestVector, shouldPass bool) { +func runSignTest(t *testing.T, priv *mldsa.PrivateKey, tv wycheproof.MlDsaSignTestVector, shouldPass bool) { t.Helper() var msg, μ []byte @@ -213,9 +210,7 @@ if pk, ok := tg.PublicKey.(string); ok { expectedPublicKey = wycheproof.MustDecodeHex(pk) } - for _, raw := range tg.Tests { - tv := decodeMLDSASignTestVector(t, raw) - + for _, tv := range tg.Tests { t.Run(wycheproof.TestName(file, tv), func(t *testing.T) { t.Parallel() @@ -242,7 +237,7 @@ } } } -func runRandomizedSignTest(t *testing.T, priv *internalmldsa.PrivateKey, tv mldsaSignTestVector, shouldPass bool) { +func runRandomizedSignTest(t *testing.T, priv *internalmldsa.PrivateKey, tv wycheproof.MlDsaSignTestVector, shouldPass bool) { t.Helper() var msg, μ []byte @@ -334,8 +329,7 @@ if pk, ok := tg.PublicKey.(string); ok { expectedPublicKey = wycheproof.MustDecodeHex(pk) } - for _, raw := range tg.Tests { - tv := decodeMLDSASignTestVector(t, raw) + for _, tv := range tg.Tests { t.Run(wycheproof.TestName(file, tv), func(t *testing.T) { t.Parallel() @@ -381,34 +375,3 @@ } t.Fatalf("unknown algorithm: %s", algorithm) return nil } - -// mldsaSignTestVector is a typed view of wycheproof.MlDsaSignTestVector, -// which the schema generator emits as interface{} because of the schema's -// conditional clauses. -type mldsaSignTestVector struct { - TcId int `json:"tcId"` - Comment string `json:"comment"` - Msg *string `json:"msg,omitempty"` - Ctx *string `json:"ctx,omitempty"` - Mu *string `json:"mu,omitempty"` - Rnd *string `json:"rnd,omitempty"` - Sig string `json:"sig"` - Result wycheproof.Result `json:"result"` - Flags []string `json:"flags"` -} - -// decodeMLDSASignTestVector roundtrips an interface{} typed raw -// MlDsaSignTestVector to produce a typed MLDSASignTestVector. -// This is a workaround for a limitation of the schema generator. -func decodeMLDSASignTestVector(t *testing.T, raw wycheproof.MlDsaSignTestVector) mldsaSignTestVector { - t.Helper() - b, err := json.Marshal(raw) - if err != nil { - t.Fatalf("re-marshal sign test vector: %v", err) - } - var tv mldsaSignTestVector - if err := json.Unmarshal(b, &tv); err != nil { - t.Fatalf("decode sign test vector: %v", err) - } - return tv -} diff --git a/src/net/http/internal/http2/transport.go b/src/net/http/internal/http2/transport.go index beab55f706757ba8ef24d8b3515d331e4c98a6fc..0b32ea72da0246466c2035091da343003dfb4117 100644 --- a/src/net/http/internal/http2/transport.go +++ b/src/net/http/internal/http2/transport.go @@ -2319,6 +2319,14 @@ // No pseudo header fields are defined for trailers. // TODO: ConnectionError might be overly harsh? Check. return ConnectionError(ErrCodeProtocol) } + if f.Truncated { + rl.endStreamError(cs, StreamError{ + StreamID: f.StreamID, + Code: ErrCodeProtocol, + Cause: errResponseHeaderListSize, + }) + return nil + } trailer := make(Header) for _, hf := range f.RegularFields() { diff --git a/src/net/http/internal/http2/transport_test.go b/src/net/http/internal/http2/transport_test.go index 3f45206b2f288e0c8c7194d4b370c004fa2b8166..e3093f64e39380ab1ea74d9e014b81283fe70660 100644 --- a/src/net/http/internal/http2/transport_test.go +++ b/src/net/http/internal/http2/transport_test.go @@ -1360,8 +1360,14 @@ checkRoundTrip(req, ErrRequestHeaderListSize, "Single large trailer") } func TestTransportChecksResponseHeaderListSize(t *testing.T) { - synctest.Test(t, testTransportChecksResponseHeaderListSize) + t.Run("headers", func(t *testing.T) { + synctest.Test(t, testTransportChecksResponseHeaderListSize) + }) + t.Run("trailers", func(t *testing.T) { + synctest.Test(t, testTransportChecksResponseTrailerHeaderListSize) + }) } + func testTransportChecksResponseHeaderListSize(t *testing.T) { tc := newTestClientConn(t) tc.greet() @@ -1406,6 +1412,55 @@ } } t.Fatalf("RoundTrip Error = %v (and %d bytes of response headers); want errResponseHeaderListSize", err, size) } +} + +func testTransportChecksResponseTrailerHeaderListSize(t *testing.T) { + tc := newTestClientConn(t) + tc.greet() + + req, _ := http.NewRequest("GET", "https://dummy.tld/", nil) + rt := tc.roundTrip(req) + + tc.wantFrameType(FrameHeaders) + tc.writeHeaders(HeadersFrameParam{ + StreamID: rt.streamID(), + EndHeaders: true, + EndStream: false, + BlockFragment: tc.makeHeaderBlockFragment( + ":status", "200", + "trailer", "x-trailer", + ), + }) + rt.wantStatus(200) + + var hdr []string + large := strings.Repeat("a", 1<<10) + for range 5042 { + hdr = append(hdr, large, large) + } + hbf := tc.makeHeaderBlockFragment(hdr...) + // Note: this number might change if our hpack implementation changes. + if size, want := len(hbf), 6328; size != want { + t.Fatalf("encoding over 10MB of duplicate keypairs took %d bytes; expected %d", size, want) + } + tc.writeHeaders(HeadersFrameParam{ + StreamID: rt.streamID(), + EndHeaders: true, + EndStream: true, + BlockFragment: hbf, + }) + + _, err := rt.readBody() + if e, ok := err.(StreamError); ok { + err = e.Cause + } + if err != ErrResponseHeaderListSize { + t.Errorf("Read = %v, want %v", err, ErrResponseHeaderListSize) + } + // Verify that this is treated as a StreamError that does not close the + // whole connection down. + tc.wantFrameType(FrameRSTStream) + tc.wantIdle() } func TestTransportCookieHeaderSplit(t *testing.T) { synctest.Test(t, testTransportCookieHeaderSplit) } @@ -3448,6 +3503,11 @@ } }, optQuiet, ) + // Make the server accept as much headers as the client plans + // on sending. + // Also liberally allow an additional 30 headers to account + // for the client automatically adding inferred headers. + ts.Config.MaxHeaderValueCount = 30 + nReqHeaders tr := newTransport(b) diff --git a/test/codegen/simd.go b/test/codegen/simd.go index 6c404a4536bfde73557a8d1c2bf14c5f47a2cdef..78764f5083fea7ee94ca34ccc3fe918100438498 100644 --- a/test/codegen/simd.go +++ b/test/codegen/simd.go @@ -113,25 +113,25 @@ } func aLtbLtc8_avx512(a, b, c archsimd.Int8x64) archsimd.Mask8x64 { // the vector length implies AVX512 implies the mask operations. - // amd64:`KANDB` + // amd64:`KANDQ` return a.Less(b).And(b.Less(c)) } func aLtbORbLtc8_avx512(a, b, c archsimd.Int8x64) archsimd.Mask8x64 { // the vector length implies AVX512 implies the mask operations. - // amd64:`KORB` + // amd64:`KORQ` return a.Less(b).Or(b.Less(c)) } func aLtbLtc64_avx512(a, b, c archsimd.Int64x8) archsimd.Mask64x8 { // the vector length implies AVX512 implies the mask operations. - // amd64:`KANDQ` + // amd64:`KANDB` return a.Less(b).And(b.Less(c)) } func aLtbORbLtc64_avx512(a, b, c archsimd.Int64x8) archsimd.Mask64x8 { // the vector length implies AVX512 implies the mask operations. - // amd64:`KORQ` + // amd64:`KORB` return a.Less(b).Or(b.Less(c)) }