From: Filippo Valsorda Date: Wed, 12 May 2021 17:23:21 +0000 (+0200) Subject: [dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto X-Git-Tag: go1.19beta1~484^2~47 X-Git-Url: http://www.git.cypherpunks.ru/?a=commitdiff_plain;h=ed1f812cefc3ece4b21241ba4cba0272cd2484ed;p=gostls13.git [dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto There used to be two BoringCrypto-specific behaviors related to cipher suites in crypto/tls: 1. in FIPS-only mode, only a restricted set of AES ciphers is allowed 2. NOT in FIPS-only mode, AES would be prioritized over ChaCha20 even if AES hardware was not available The motivation of (2) is unclear, and BoringSSL doesn't have equivalent logic. This merge drops (2), and keeps (1). Note that the list of FIPS-only ciphers does not have priority semantics anymore, but the default logic still sorts them the same way as they used to be. Change-Id: I50544011085cfa2b087f323aebf5338c0bd2dd33 --- ed1f812cefc3ece4b21241ba4cba0272cd2484ed diff --cc src/crypto/ed25519/ed25519_test.go index adb09e409a,8a973b36ea..84fdc3ca8b --- a/src/crypto/ed25519/ed25519_test.go +++ b/src/crypto/ed25519/ed25519_test.go @@@ -204,6 -185,24 +185,25 @@@ func TestMalleability(t *testing.T) } } + func TestAllocations(t *testing.T) { ++ t.Skip("skipping allocations test on Go+BoringCrypto, as cgo causes allocations") + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + seed := make([]byte, SeedSize) + message := []byte("Hello, world!") + priv := NewKeyFromSeed(seed) + pub := priv.Public().(PublicKey) + signature := Sign(priv, message) + if !Verify(pub, message, signature) { + t.Fatal("signature didn't verify") + } + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1v", allocs) + } + } + func BenchmarkKeyGeneration(b *testing.B) { var zero zeroReader for i := 0; i < b.N; i++ { diff --cc src/crypto/ed25519/internal/edwards25519/edwards25519_test.go index 0000000000,8031256525..69fdcfea7a mode 000000,100644..100644 --- a/src/crypto/ed25519/internal/edwards25519/edwards25519_test.go +++ b/src/crypto/ed25519/internal/edwards25519/edwards25519_test.go @@@ -1,0 -1,304 +1,305 @@@ + // Copyright (c) 2019 The Go Authors. All rights reserved. + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + + package edwards25519 + + import ( + "crypto/ed25519/internal/edwards25519/field" + "encoding/hex" + "os" + "reflect" + "strings" + "testing" + ) + + var B = NewGeneratorPoint() + var I = NewIdentityPoint() + + func checkOnCurve(t *testing.T, points ...*Point) { + t.Helper() + for i, p := range points { + var XX, YY, ZZ, ZZZZ field.Element + XX.Square(&p.x) + YY.Square(&p.y) + ZZ.Square(&p.z) + ZZZZ.Square(&ZZ) + // -x² + y² = 1 + dx²y² + // -(X/Z)² + (Y/Z)² = 1 + d(X/Z)²(Y/Z)² + // (-X² + Y²)/Z² = 1 + (dX²Y²)/Z⁴ + // (-X² + Y²)*Z² = Z⁴ + dX²Y² + var lhs, rhs field.Element + lhs.Subtract(&YY, &XX).Multiply(&lhs, &ZZ) + rhs.Multiply(d, &XX).Multiply(&rhs, &YY).Add(&rhs, &ZZZZ) + if lhs.Equal(&rhs) != 1 { + t.Errorf("X, Y, and Z do not specify a point on the curve\nX = %v\nY = %v\nZ = %v", p.x, p.y, p.z) + } + // xy = T/Z + lhs.Multiply(&p.x, &p.y) + rhs.Multiply(&p.z, &p.t) + if lhs.Equal(&rhs) != 1 { + t.Errorf("point %d is not valid\nX = %v\nY = %v\nZ = %v", i, p.x, p.y, p.z) + } + } + } + + func TestGenerator(t *testing.T) { + // These are the coordinates of B from RFC 8032, Section 5.1, converted to + // little endian hex. + x := "1ad5258f602d56c9b2a7259560c72c695cdcd6fd31e2a4c0fe536ecdd3366921" + y := "5866666666666666666666666666666666666666666666666666666666666666" + if got := hex.EncodeToString(B.x.Bytes()); got != x { + t.Errorf("wrong B.x: got %s, expected %s", got, x) + } + if got := hex.EncodeToString(B.y.Bytes()); got != y { + t.Errorf("wrong B.y: got %s, expected %s", got, y) + } + if B.z.Equal(feOne) != 1 { + t.Errorf("wrong B.z: got %v, expected 1", B.z) + } + // Check that t is correct. + checkOnCurve(t, B) + } + + func TestAddSubNegOnBasePoint(t *testing.T) { + checkLhs, checkRhs := &Point{}, &Point{} + + checkLhs.Add(B, B) + tmpP2 := new(projP2).FromP3(B) + tmpP1xP1 := new(projP1xP1).Double(tmpP2) + checkRhs.fromP1xP1(tmpP1xP1) + if checkLhs.Equal(checkRhs) != 1 { + t.Error("B + B != [2]B") + } + checkOnCurve(t, checkLhs, checkRhs) + + checkLhs.Subtract(B, B) + Bneg := new(Point).Negate(B) + checkRhs.Add(B, Bneg) + if checkLhs.Equal(checkRhs) != 1 { + t.Error("B - B != B + (-B)") + } + if I.Equal(checkLhs) != 1 { + t.Error("B - B != 0") + } + if I.Equal(checkRhs) != 1 { + t.Error("B + (-B) != 0") + } + checkOnCurve(t, checkLhs, checkRhs, Bneg) + } + + func TestComparable(t *testing.T) { + if reflect.TypeOf(Point{}).Comparable() { + t.Error("Point is unexpectedly comparable") + } + } + + func TestInvalidEncodings(t *testing.T) { + // An invalid point, that also happens to have y > p. + invalid := "efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f" + p := NewGeneratorPoint() + if out, err := p.SetBytes(decodeHex(invalid)); err == nil { + t.Error("expected error for invalid point") + } else if out != nil { + t.Error("SetBytes did not return nil on an invalid encoding") + } else if p.Equal(B) != 1 { + t.Error("the Point was modified while decoding an invalid encoding") + } + checkOnCurve(t, p) + } + + func TestNonCanonicalPoints(t *testing.T) { + type test struct { + name string + encoding, canonical string + } + tests := []test{ + // Points with x = 0 and the sign bit set. With x = 0 the curve equation + // gives y² = 1, so y = ±1. 1 has two valid encodings. + { + "y=1,sign-", + "0100000000000000000000000000000000000000000000000000000000000080", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+1,sign-", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p-1,sign-", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + }, + + // Non-canonical y encodings with values 2²⁵⁵-19 (p) to 2²⁵⁵-1 (p+18). + { + "y=p,sign+", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p,sign-", + "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0000000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+1,sign+", + "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0100000000000000000000000000000000000000000000000000000000000000", + }, + // "y=p+1,sign-" is already tested above. + // p+2 is not a valid y-coordinate. + { + "y=p+3,sign+", + "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0300000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+3,sign-", + "f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0300000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+4,sign+", + "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0400000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+4,sign-", + "f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0400000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+5,sign+", + "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0500000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+5,sign-", + "f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0500000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+6,sign+", + "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0600000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+6,sign-", + "f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0600000000000000000000000000000000000000000000000000000000000080", + }, + // p+7 is not a valid y-coordinate. + // p+8 is not a valid y-coordinate. + { + "y=p+9,sign+", + "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0900000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+9,sign-", + "f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0900000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+10,sign+", + "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0a00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+10,sign-", + "f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0a00000000000000000000000000000000000000000000000000000000000080", + }, + // p+11 is not a valid y-coordinate. + // p+12 is not a valid y-coordinate. + // p+13 is not a valid y-coordinate. + { + "y=p+14,sign+", + "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0e00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+14,sign-", + "fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0e00000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+15,sign+", + "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "0f00000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+15,sign-", + "fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "0f00000000000000000000000000000000000000000000000000000000000080", + }, + { + "y=p+16,sign+", + "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "1000000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+16,sign-", + "fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1000000000000000000000000000000000000000000000000000000000000080", + }, + // p+17 is not a valid y-coordinate. + { + "y=p+18,sign+", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", + "1200000000000000000000000000000000000000000000000000000000000000", + }, + { + "y=p+18,sign-", + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "1200000000000000000000000000000000000000000000000000000000000080", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p1, err := new(Point).SetBytes(decodeHex(tt.encoding)) + if err != nil { + t.Fatalf("error decoding non-canonical point: %v", err) + } + p2, err := new(Point).SetBytes(decodeHex(tt.canonical)) + if err != nil { + t.Fatalf("error decoding canonical point: %v", err) + } + if p1.Equal(p2) != 1 { + t.Errorf("equivalent points are not equal: %v, %v", p1, p2) + } + if encoding := hex.EncodeToString(p1.Bytes()); encoding != tt.canonical { + t.Errorf("re-encoding does not match canonical; got %q, expected %q", encoding, tt.canonical) + } + checkOnCurve(t, p1, p2) + }) + } + } + + var testAllocationsSink byte + + func TestAllocations(t *testing.T) { ++ t.Skip("skipping allocations test on Go+BoringCrypto, as cgo causes allocations") + if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-noopt") { + t.Skip("skipping allocations test without relevant optimizations") + } + if allocs := testing.AllocsPerRun(100, func() { + p := NewIdentityPoint() + p.Add(p, NewGeneratorPoint()) + s := NewScalar() + testAllocationsSink ^= s.Bytes()[0] + testAllocationsSink ^= p.Bytes()[0] + }); allocs > 0 { + t.Errorf("expected zero allocations, got %0.1v", allocs) + } + } + + func decodeHex(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic(err) + } + return b + } diff --cc src/crypto/rsa/pss_test.go index 32f6f0c3aa,c3a6d46849..51f9760187 --- a/src/crypto/rsa/pss_test.go +++ b/src/crypto/rsa/pss_test.go @@@ -9,9 -9,10 +9,9 @@@ import "bytes" "compress/bzip2" "crypto" - _ "crypto/md5" "crypto/rand" "crypto/sha1" - _ "crypto/sha256" + "crypto/sha256" "encoding/hex" "math/big" "os" diff --cc src/crypto/tls/auth.go index 17595f0c35,a9df0da6d6..7c5675c6d9 --- a/src/crypto/tls/auth.go +++ b/src/crypto/tls/auth.go @@@ -169,6 -169,6 +169,7 @@@ var rsaSignatureSchemes = []struct // and optionally filtered by its explicit SupportedSignatureAlgorithms. // // This function must be kept in sync with supportedSignatureAlgorithms. ++// FIPS filtering is applied in the caller, selectSignatureScheme. func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme { priv, ok := cert.PrivateKey.(crypto.Signer) if !ok { diff --cc src/crypto/tls/boring.go index d61deb5b81,0000000000..09f71c1691 mode 100644,000000..100644 --- a/src/crypto/tls/boring.go +++ b/src/crypto/tls/boring.go @@@ -1,132 -1,0 +1,127 @@@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package tls + +import ( + "crypto/ecdsa" - "crypto/internal/boring" + "crypto/internal/boring/fipstls" + "crypto/rsa" + "crypto/x509" +) + - // boringEnabled is an alias of boring.Enabled to avoid a new import in common.go. - const boringEnabled = boring.Enabled - +// needFIPS returns fipstls.Required(); it avoids a new import in common.go. +func needFIPS() bool { + return fipstls.Required() +} + +// fipsMinVersion replaces c.minVersion in FIPS-only mode. +func fipsMinVersion(c *Config) uint16 { + // FIPS requires TLS 1.2. + return VersionTLS12 +} + +// fipsMaxVersion replaces c.maxVersion in FIPS-only mode. +func fipsMaxVersion(c *Config) uint16 { + // FIPS requires TLS 1.2. + return VersionTLS12 +} + +// default defaultFIPSCurvePreferences is the FIPS-allowed curves, +// in preference order (most preferable first). +var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521} + +// fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode. +func fipsCurvePreferences(c *Config) []CurveID { + if c == nil || len(c.CurvePreferences) == 0 { + return defaultFIPSCurvePreferences + } + var list []CurveID + for _, id := range c.CurvePreferences { + for _, allowed := range defaultFIPSCurvePreferences { + if id == allowed { + list = append(list, id) + break + } + } + } + return list +} + - // default FIPSCipherSuites is the FIPS-allowed cipher suites, - // in preference order (most preferable first). - var defaultFIPSCipherSuites = []uint16{ ++// defaultCipherSuitesFIPS are the FIPS-allowed cipher suites. ++var defaultCipherSuitesFIPS = []uint16{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_RSA_WITH_AES_128_GCM_SHA256, + TLS_RSA_WITH_AES_256_GCM_SHA384, +} + +// fipsCipherSuites replaces c.cipherSuites in FIPS-only mode. +func fipsCipherSuites(c *Config) []uint16 { + if c == nil || c.CipherSuites == nil { - return defaultFIPSCipherSuites ++ return defaultCipherSuitesFIPS + } - var list []uint16 ++ list := make([]uint16, 0, len(defaultCipherSuitesFIPS)) + for _, id := range c.CipherSuites { - for _, allowed := range defaultFIPSCipherSuites { ++ for _, allowed := range defaultCipherSuitesFIPS { + if id == allowed { + list = append(list, id) + break + } + } + } + return list +} + +// isBoringCertificate reports whether a certificate may be used +// when constructing a verified chain. +// It is called for each leaf, intermediate, and root certificate. +func isBoringCertificate(c *x509.Certificate) bool { + if !needFIPS() { + // Everything is OK if we haven't forced FIPS-only mode. + return true + } + + // Otherwise the key must be RSA 2048, RSA 3072, or ECDSA P-256. + switch k := c.PublicKey.(type) { + default: + return false + case *rsa.PublicKey: + if size := k.N.BitLen(); size != 2048 && size != 3072 { + return false + } + case *ecdsa.PublicKey: + if name := k.Curve.Params().Name; name != "P-256" && name != "P-384" { + return false + } + } + + return true +} + +// fipsSupportedSignatureAlgorithms currently are a subset of +// defaultSupportedSignatureAlgorithms without Ed25519 and SHA-1. +var fipsSupportedSignatureAlgorithms = []SignatureScheme{ + PSSWithSHA256, + PSSWithSHA384, + PSSWithSHA512, + PKCS1WithSHA256, + ECDSAWithP256AndSHA256, + PKCS1WithSHA384, + ECDSAWithP384AndSHA384, + PKCS1WithSHA512, + ECDSAWithP521AndSHA512, +} + +// supportedSignatureAlgorithms returns the supported signature algorithms. +func supportedSignatureAlgorithms() []SignatureScheme { + if !needFIPS() { + return defaultSupportedSignatureAlgorithms + } + return fipsSupportedSignatureAlgorithms +} + +var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme diff --cc src/crypto/tls/cipher_suites.go index 6596562fb1,4bf06468c6..e07d742bd3 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@@ -349,13 -510,7 +518,16 @@@ func aeadAESGCM(key, noncePrefix []byte if err != nil { panic(err) } - aead, err := cipher.NewGCM(aes) ++ type gcmtls interface { ++ NewGCMTLS() (cipher.AEAD, error) ++ } + var aead cipher.AEAD + if aesTLS, ok := aes.(gcmtls); ok { + aead, err = aesTLS.NewGCMTLS() + } else { + boring.Unreachable() + aead, err = cipher.NewGCM(aes) + } if err != nil { panic(err) } diff --cc src/crypto/tls/common.go index 2564dfee9e,77957ef82b..ca93d4341d --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@@ -925,14 -951,10 +951,13 @@@ func (c *Config) time() time.Time } func (c *Config) cipherSuites() []uint16 { + if needFIPS() { + return fipsCipherSuites(c) + } - s := c.CipherSuites - if s == nil { - s = defaultCipherSuites() + if c.CipherSuites != nil { + return c.CipherSuites } - return s + return defaultCipherSuites } var supportedVersions = []uint16{ diff --cc src/go/build/deps_test.go index e04b07d3a9,bb6d92f89a..a2423cf0d9 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@@ -390,15 -392,21 +395,16 @@@ var depsRules = < crypto < crypto/subtle < crypto/internal/subtle + < crypto/ed25519/internal/edwards25519/field + < crypto/ed25519/internal/edwards25519 < crypto/cipher + < encoding/asn1 + < crypto/internal/boring < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4, crypto/sha1, crypto/sha256, crypto/sha512 - < CRYPTO; - - CGO, fmt, net !< CRYPTO; - - # CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok. - CRYPTO, FMT, math/big < crypto/rand < crypto/internal/randutil - < crypto/ed25519/internal/edwards25519 < crypto/ed25519 - < encoding/asn1 < golang.org/x/crypto/cryptobyte/asn1 < golang.org/x/crypto/cryptobyte < golang.org/x/crypto/curve25519