Skip to content

Commit 3812fb0

Browse files
committed
[FAB-7525] Strong ciphers for TLS
While Fabric only supports TLS 1.2, it currently uses the default set of ciphers provided by Go. This change sets the default ciphers to a very strong set (AESGCM). While the code is structured to allow these to be configured in the future, this change does not allow the ciphers to be configured. Change-Id: I6bb68454adacadac63bef3ce89c25e4c687e482b Signed-off-by: Gari Singh <gari.r.singh@gmail.com>
1 parent f0ad551 commit 3812fb0

File tree

3 files changed

+124
-9
lines changed

3 files changed

+124
-9
lines changed

core/comm/config.go

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
77
package comm
88

99
import (
10+
"crypto/tls"
1011
"time"
1112

1213
"github.com/spf13/viper"
@@ -30,6 +31,15 @@ var (
3031
ServerTimeout: time.Duration(20) * time.Second, // 20 sec - gRPC default
3132
ServerMinInterval: time.Duration(1) * time.Minute, // match ClientInterval
3233
}
34+
// strong TLS cipher suites
35+
tlsCipherSuites = []uint16{
36+
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
37+
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
38+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
39+
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
40+
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
41+
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
42+
}
3343
)
3444

3545
// ServerConfig defines the parameters for configuring a GRPCServer instance
@@ -43,20 +53,22 @@ type ServerConfig struct {
4353
// SecureOptions defines the security parameters (e.g. TLS) for a
4454
// GRPCServer instance
4555
type SecureOptions struct {
46-
//PEM-encoded X509 public key to be used by the server for TLS communication
56+
// PEM-encoded X509 public key to be used by the server for TLS communication
4757
ServerCertificate []byte
48-
//PEM-encoded private key to be used by the server for TLS communication
58+
// PEM-encoded private key to be used by the server for TLS communication
4959
ServerKey []byte
50-
//Set of PEM-encoded X509 certificate authorities to optionally send
51-
//as part of the server handshake
60+
// Set of PEM-encoded X509 certificate authorities to optionally send
61+
// as part of the server handshake
5262
ServerRootCAs [][]byte
53-
//Set of PEM-encoded X509 certificate authorities to use when verifying
54-
//client certificates
63+
// Set of PEM-encoded X509 certificate authorities to use when verifying
64+
// client certificates
5565
ClientRootCAs [][]byte
56-
//Whether or not to use TLS for communication
66+
// Whether or not to use TLS for communication
5767
UseTLS bool
58-
//Whether or not TLS client must present certificates for authentication
68+
// Whether or not TLS client must present certificates for authentication
5969
RequireClientCert bool
70+
// CipherSuites is a list of supported cipher suites for TLS
71+
CipherSuites []uint16
6072
}
6173

6274
// KeepAliveOptions is used to set the gRPC keepalive settings for both

core/comm/server.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ func NewGRPCServerFromListener(listener net.Listener, serverConfig ServerConfig)
119119
grpcServer.serverCertificate.Store(cert)
120120

121121
//set up our TLS config
122-
122+
if len(secureConfig.CipherSuites) == 0 {
123+
secureConfig.CipherSuites = tlsCipherSuites
124+
}
123125
getCert := func(_ *tls.ClientHelloInfo) (*tls.Certificate, error) {
124126
cert := grpcServer.serverCertificate.Load().(tls.Certificate)
125127
return &cert, nil
@@ -128,6 +130,7 @@ func NewGRPCServerFromListener(listener net.Listener, serverConfig ServerConfig)
128130
grpcServer.tlsConfig = &tls.Config{
129131
GetCertificate: getCert,
130132
SessionTicketsDisabled: true,
133+
CipherSuites: secureConfig.CipherSuites,
131134
}
132135
grpcServer.tlsConfig.ClientAuth = tls.RequestClientCert
133136
//check if client authentication is required

core/comm/server_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,3 +1490,103 @@ func TestUpdateTLSCert(t *testing.T) {
14901490
assert.Error(t, err)
14911491
assert.Contains(t, err.Error(), "certificate is valid for notlocalhost.org1.example.com, notlocalhost, not localhost")
14921492
}
1493+
1494+
func TestCipherSuites(t *testing.T) {
1495+
t.Parallel()
1496+
1497+
// default cipher suites
1498+
defaultCipherSuites := []uint16{
1499+
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
1500+
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
1501+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
1502+
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
1503+
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
1504+
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
1505+
}
1506+
// the other cipher suites supported by Go
1507+
otherCipherSuites := []uint16{
1508+
tls.TLS_RSA_WITH_RC4_128_SHA,
1509+
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
1510+
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
1511+
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
1512+
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
1513+
tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
1514+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
1515+
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
1516+
tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
1517+
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
1518+
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
1519+
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
1520+
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
1521+
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
1522+
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
1523+
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
1524+
}
1525+
certPEM, err := ioutil.ReadFile(filepath.Join("testdata", "certs",
1526+
"Org1-server1-cert.pem"))
1527+
assert.NoError(t, err)
1528+
keyPEM, err := ioutil.ReadFile(filepath.Join("testdata", "certs",
1529+
"Org1-server1-key.pem"))
1530+
assert.NoError(t, err)
1531+
caPEM, err := ioutil.ReadFile(filepath.Join("testdata", "certs",
1532+
"Org1-cert.pem"))
1533+
assert.NoError(t, err)
1534+
certPool, err := createCertPool([][]byte{caPEM})
1535+
assert.NoError(t, err)
1536+
1537+
serverConfig := comm.ServerConfig{
1538+
SecOpts: &comm.SecureOptions{
1539+
ServerCertificate: certPEM,
1540+
ServerKey: keyPEM,
1541+
UseTLS: true,
1542+
}}
1543+
1544+
var tests = []struct {
1545+
name string
1546+
port int
1547+
clientCiphers []uint16
1548+
success bool
1549+
}{
1550+
{
1551+
name: "server default / client all",
1552+
port: 8340,
1553+
success: true,
1554+
},
1555+
{
1556+
name: "server default / client match",
1557+
port: 8341,
1558+
clientCiphers: defaultCipherSuites,
1559+
success: true,
1560+
},
1561+
{
1562+
name: "server default / client no match",
1563+
port: 8342,
1564+
clientCiphers: otherCipherSuites,
1565+
success: false,
1566+
},
1567+
}
1568+
1569+
for _, test := range tests {
1570+
test := test
1571+
t.Run(test.name, func(t *testing.T) {
1572+
t.Parallel()
1573+
t.Logf("Running test %s ...", test.name)
1574+
address := fmt.Sprintf("localhost:%d", test.port)
1575+
srv, err := comm.NewGRPCServer(address, serverConfig)
1576+
assert.NoError(t, err)
1577+
go srv.Start()
1578+
defer srv.Stop()
1579+
tlsConfig := &tls.Config{
1580+
RootCAs: certPool,
1581+
CipherSuites: test.clientCiphers,
1582+
}
1583+
_, err = tls.Dial("tcp", address, tlsConfig)
1584+
if test.success {
1585+
assert.NoError(t, err)
1586+
} else {
1587+
t.Log(err)
1588+
assert.Contains(t, err.Error(), "handshake failure")
1589+
}
1590+
})
1591+
}
1592+
}

0 commit comments

Comments
 (0)