فهرست منبع

don't panic on bad ed25519 key lengths (#1601)

* don't panic on bad ed25519 key lengths

* don't allow mismatched curves

* add test
Jack Doan 5 ماه پیش
والد
کامیت
a82a8dc547
5فایلهای تغییر یافته به همراه39 افزوده شده و 0 حذف شده
  1. 4 0
      cert/ca_pool.go
  2. 28 0
      cert/ca_pool_test.go
  3. 3 0
      cert/cert_v1.go
  4. 3 0
      cert/cert_v2.go
  5. 1 0
      cert/errors.go

+ 4 - 0
cert/ca_pool.go

@@ -217,6 +217,10 @@ func (ncp *CAPool) verify(c Certificate, now time.Time, certFp string, signerFp
 		return nil, err
 	}
 
+	if signer.Certificate.Curve() != c.Curve() {
+		return nil, ErrCurveMismatch
+	}
+
 	if signer.Certificate.Expired(now) {
 		return nil, ErrRootExpired
 	}

+ 28 - 0
cert/ca_pool_test.go

@@ -654,3 +654,31 @@ func TestCertificateV2_Verify_Subnets(t *testing.T) {
 	_, err = caPool.VerifyCertificate(time.Now(), c)
 	require.NoError(t, err)
 }
+
+func TestCertificateV2_CurveMismatch(t *testing.T) {
+	caIp1 := mustParsePrefixUnmapped("10.0.0.0/16")
+	caIp2 := mustParsePrefixUnmapped("192.168.0.0/24")
+	ca, _, caKey, _ := NewTestCaCert(Version2, Curve_P256, time.Now(), time.Now().Add(10*time.Minute), []netip.Prefix{caIp1, caIp2}, nil, []string{"test"})
+
+	caPem, err := ca.MarshalPEM()
+	require.NoError(t, err)
+
+	caPool := NewCAPool()
+	b, err := caPool.AddCAFromPEM(caPem)
+	require.NoError(t, err)
+	assert.Empty(t, b)
+
+	// ip is outside the network
+	cIp1 := mustParsePrefixUnmapped("10.0.0.1/24")
+	c, _, _, _ := NewTestCert(Version2, Curve_P256, ca, caKey, "test", time.Now(), time.Now().Add(5*time.Minute), []netip.Prefix{cIp1}, nil, []string{"test"})
+
+	fp, _ := c.Fingerprint()
+	_, err = caPool.verify(c, time.Now(), fp, c.Issuer())
+	require.NoError(t, err)
+	//
+	c2 := c.(*certificateV2)
+	c2.curve = Curve_CURVE25519
+	fp, _ = c.Fingerprint()
+	_, err = caPool.verify(c, time.Now(), fp, c.Issuer())
+	require.Error(t, err)
+}

+ 3 - 0
cert/cert_v1.go

@@ -112,6 +112,9 @@ func (c *certificateV1) CheckSignature(key []byte) bool {
 	}
 	switch c.details.curve {
 	case Curve_CURVE25519:
+		if len(key) != ed25519.PublicKeySize {
+			return false //avoids a panic internal to ed25519
+		}
 		return ed25519.Verify(key, b, c.signature)
 	case Curve_P256:
 		pubKey, err := ecdsa.ParseUncompressedPublicKey(elliptic.P256(), key)

+ 3 - 0
cert/cert_v2.go

@@ -151,6 +151,9 @@ func (c *certificateV2) CheckSignature(key []byte) bool {
 
 	switch c.curve {
 	case Curve_CURVE25519:
+		if len(key) != ed25519.PublicKeySize {
+			return false //avoids a panic internal to ed25519
+		}
 		return ed25519.Verify(key, b, c.signature)
 	case Curve_P256:
 		pubKey, err := ecdsa.ParseUncompressedPublicKey(elliptic.P256(), key)

+ 1 - 0
cert/errors.go

@@ -22,6 +22,7 @@ var (
 	ErrCaNotFound                 = errors.New("could not find ca for the certificate")
 	ErrUnknownVersion             = errors.New("certificate version unrecognized")
 	ErrCertPubkeyPresent          = errors.New("certificate has unexpected pubkey present")
+	ErrCurveMismatch              = errors.New("certificate curve does not match CA")
 
 	ErrInvalidPEMBlock                   = errors.New("input did not contain a valid PEM encoded block")
 	ErrInvalidPEMCertificateBanner       = errors.New("bytes did not contain a proper certificate banner")