SIDH: Implement test againt TLSv1.2

Tris tries to connect to BoringSSL over TLS 1.2 with X25519-SIDH
as prefered DH group. As this is not supported by BoringSSL it must
fall back to P-256 (second preference on the list)

Also refactors tris test client
This commit is contained in:
Henry Case 2018-12-07 15:35:53 +00:00 committed by Kris Kwiatkowski
parent 334eee5310
commit 76231e7564
5 changed files with 62 additions and 42 deletions

4
13.go
View File

@ -1231,7 +1231,7 @@ func (kexSIDHp503) generate(c *Conn, groupId CurveID) ([]byte, keyShare, error)
return nil, keyShare{}, errors.New("tls: private SIDH key generation failed") return nil, keyShare{}, errors.New("tls: private SIDH key generation failed")
} }
pubKey := prvKey.GeneratePublicKey() pubKey := prvKey.GeneratePublicKey()
return prvKey.Export(), keyShare{group: 0, data: pubKey.Export()}, nil return prvKey.Export(), keyShare{group: 0 /*UNUSED*/, data: pubKey.Export()}, nil
} }
func (kexSIDHp503) derive(c *Conn, ks keyShare, key []byte) []byte { func (kexSIDHp503) derive(c *Conn, ks keyShare, key []byte) []byte {
@ -1295,7 +1295,7 @@ func (kex *kexHybridSIDHp503X25519) derive(c *Conn, ks keyShare, key []byte) []b
copy(sharedKey[:], ret) copy(sharedKey[:], ret)
// Key agreement for PQ // Key agreement for PQ
tmpKs.group = 0 tmpKs.group = 0 /*UNUSED*/
tmpKs.data = ks.data[x25519SharedSecretSz:] tmpKs.data = ks.data[x25519SharedSecretSz:]
ret = kex.pqKEX.derive(c, tmpKs, key[x25519SharedSecretSz:]) ret = kex.pqKEX.derive(c, tmpKs, key[x25519SharedSecretSz:])
if ret == nil { if ret == nil {

View File

@ -59,7 +59,7 @@ ADD sidh_$REVISION.patch /
RUN cd boringssl && git fetch RUN cd boringssl && git fetch
RUN cd boringssl && git checkout $REVISION RUN cd boringssl && git checkout $REVISION
RUN cd boringssl && patch -p1 < /sidh_$REVISION.patch RUN cd boringssl && patch -p1 < /sidh_$REVISION.patch
RUN cd boringssl/build && cmake -DEXP_SIDH=1 -GNinja .. RUN cd boringssl/build && cmake -GNinja ..
RUN cd boringssl && ninja -C build RUN cd boringssl && ninja -C build
ADD httpreq.txt /httpreq.txt ADD httpreq.txt /httpreq.txt

View File

@ -25,7 +25,7 @@ bssl server \
bssl server \ bssl server \
-key ecdsa.pem \ -key ecdsa.pem \
-curves X25519-SIDHp503:X25519:P-256:P-384:P-521 \ -curves X25519-SIDHp503:X25519:P-256:P-384:P-521 \
-min-version tls1.3 -max-version tls1.3 \ -min-version tls1.2 -max-version tls1.3 \
-accept 7443 -loop -www \ -accept 7443 -loop -www \
-debug 2>&1 & -debug 2>&1 &

View File

@ -257,10 +257,21 @@ class InteropClient_BoringSSL(InteropClient, ClientNominalMixin, ClientClientAut
''' '''
Connects to BoringSSL server listening on 7443 and tries to perform key agreement with SIDH/P503-X25519 Connects to BoringSSL server listening on 7443 and tries to perform key agreement with SIDH/P503-X25519
''' '''
res = self.d.run_client(self.CLIENT_NAME, '-rsa=false -ecdsa=true -qr X25519-SIDHp503 ' + self.server_ip+":7443") res = self.d.run_client(self.CLIENT_NAME, '-rsa=false -ecdsa=true -groups X25519-SIDHp503 ' + self.server_ip+":7443")
self.assertEqual(res[0], 0) self.assertEqual(res[0], 0)
self.assertIsNotNone(re.search(RE_TRIS_ALL_PASSED, res[1], re.MULTILINE)) self.assertIsNotNone(re.search(RE_TRIS_ALL_PASSED, res[1], re.MULTILINE))
def test_SIDH_TLSv12(self):
'''
Connects to TRIS server listening on 7443 and tries to perform key agreement with SIDH/P503-X25519
This connection will be over TLSv12 and hence it should fall back to X25519
'''
res = self.d.run_client(self.CLIENT_NAME, '-tls_version=1.2 -rsa=false -ecdsa=true -groups X25519-SIDHp503:P-256 -ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ' + self.server_ip+":7443")
self.assertEqual(res[0], 0)
# Go doesn't provide API to get NamedGroup ID, but boringssl on port 7443 accepts only TLS1.2
# so if handshake was successful, then that's all what we need
self.assertIsNotNone(re.search(RE_TRIS_ALL_PASSED, res[1], re.MULTILINE))
class InteropClient_NSS( class InteropClient_NSS(
InteropClient, InteropClient,
ClientNominalMixin, ClientNominalMixin,
@ -278,7 +289,7 @@ class InteropServer_TRIS(ClientNominalMixin, InteropServer, unittest.TestCase):
self.assertEqual(res[0], 0) self.assertEqual(res[0], 0)
def test_SIDH(self): def test_SIDH(self):
res = self.d.run_client(self.CLIENT_NAME, '-rsa=false -ecdsa=true -qr X25519-SIDHp503 '+self.server_ip+":7443") res = self.d.run_client(self.CLIENT_NAME, '-rsa=false -ecdsa=true -groups X25519-SIDHp503 '+self.server_ip+":7443")
self.assertEqual(res[0], 0) self.assertEqual(res[0], 0)
def test_server_doesnt_support_SIDH(self): def test_server_doesnt_support_SIDH(self):

View File

@ -3,6 +3,7 @@ package main
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"errors"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -26,6 +27,23 @@ var cipherSuiteIdToName = map[uint16]string{
tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256", tls.TLS_CHACHA20_POLY1305_SHA256: "TLS_CHACHA20_POLY1305_SHA256",
} }
var namedGroupsToName = map[uint16]string{
uint16(tls.HybridSIDHp503Curve25519): "X25519-SIDHp503",
uint16(tls.X25519): "X25519",
uint16(tls.CurveP256): "P-256",
uint16(tls.CurveP384): "P-384",
uint16(tls.CurveP521): "P-521",
}
func getIDByName(m map[uint16]string, name string) (uint16, error) {
for key, value := range m {
if value == name {
return key, nil
}
}
return 0, errors.New("Unknown value")
}
var failed uint var failed uint
type Client struct { type Client struct {
@ -51,15 +69,6 @@ func (c *Client) setMinMaxTLS(ver uint16) {
c.TLS.MaxVersion = ver c.TLS.MaxVersion = ver
} }
func getQrAlgoId(qr string) tls.CurveID {
switch qr {
case "X25519-SIDHp503":
return tls.HybridSIDHp503Curve25519
default:
return 0
}
}
func (c *Client) run() { func (c *Client) run() {
fmt.Printf("TLS %s with %s\n", tlsVersionToName[c.TLS.MinVersion], cipherSuiteIdToName[c.TLS.CipherSuites[0]]) fmt.Printf("TLS %s with %s\n", tlsVersionToName[c.TLS.MinVersion], cipherSuiteIdToName[c.TLS.CipherSuites[0]])
@ -101,14 +110,16 @@ func result() {
// Usage client args host:port // Usage client args host:port
func main() { func main() {
var keylog_file, qrAlgoName string var keylog_file, tls_version, named_groups, named_ciphers string
var enable_rsa, enable_ecdsa, client_auth bool var enable_rsa, enable_ecdsa, client_auth bool
flag.StringVar(&keylog_file, "keylogfile", "", "Secrets will be logged here") flag.StringVar(&keylog_file, "keylogfile", "", "Secrets will be logged here")
flag.BoolVar(&enable_rsa, "rsa", true, "Whether to enable RSA cipher suites") flag.BoolVar(&enable_rsa, "rsa", true, "Whether to enable RSA cipher suites")
flag.BoolVar(&enable_ecdsa, "ecdsa", true, "Whether to enable ECDSA cipher suites") flag.BoolVar(&enable_ecdsa, "ecdsa", true, "Whether to enable ECDSA cipher suites")
flag.BoolVar(&client_auth, "cliauth", false, "Whether to enable client authentication") flag.BoolVar(&client_auth, "cliauth", false, "Whether to enable client authentication")
flag.StringVar(&qrAlgoName, "qr", "", "Specifies qr algorithm from following list:\n[X25519-SIDHp503]") flag.StringVar(&tls_version, "tls_version", "1.3", "TLS version to use")
flag.StringVar(&named_groups, "groups", "X25519:P-256:P-384:P-521", "NamedGroups IDs to use")
flag.StringVar(&named_ciphers, "ciphers", "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384", "Named cipher IDs to use")
flag.Parse() flag.Parse()
if flag.NArg() != 1 { if flag.NArg() != 1 {
flag.Usage() flag.Usage()
@ -133,21 +144,6 @@ func main() {
log.Println("Enabled keylog") log.Println("Enabled keylog")
} }
if len(qrAlgoName) > 0 {
id := getQrAlgoId(qrAlgoName)
if id == 0 {
log.Fatalf("Unknown QR algorithm: %s", qrAlgoName)
return
}
client.TLS.CipherSuites = []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
client.TLS.CurvePreferences = []tls.CurveID{id}
client.setMinMaxTLS(tls.VersionTLS13)
client.run()
result()
return
}
if client_auth { if client_auth {
var err error var err error
client_cert, err := tls.X509KeyPair([]byte(client_crt), []byte(client_key)) client_cert, err := tls.X509KeyPair([]byte(client_crt), []byte(client_key))
@ -178,17 +174,30 @@ func main() {
c.run() c.run()
} }
client.setMinMaxTLS(tls.VersionTLS13) // Set requested DH groups
client.TLS.CipherSuites = []uint16{tls.TLS_CHACHA20_POLY1305_SHA256} client.TLS.CurvePreferences = []tls.CurveID{}
client.run() for _, ng := range strings.Split(named_groups, ":") {
id, err := getIDByName(namedGroupsToName, ng)
if err != nil {
panic("Wrong TLS version provided")
}
client.TLS.CurvePreferences = append(client.TLS.CurvePreferences, tls.CurveID(id))
}
client.setMinMaxTLS(tls.VersionTLS13) // Perform TLS handshake with each each requested CipherSuite
client.TLS.CipherSuites = []uint16{tls.TLS_AES_128_GCM_SHA256} tlsID, err := getIDByName(tlsVersionToName, tls_version)
client.run() if err != nil {
panic("Unknown TLS version")
client.setMinMaxTLS(tls.VersionTLS13) }
client.TLS.CipherSuites = []uint16{tls.TLS_AES_256_GCM_SHA384} for _, cn := range strings.Split(named_ciphers, ":") {
client.run() id, err := getIDByName(cipherSuiteIdToName, cn)
if err != nil {
panic("Wrong cipher name provided")
}
client.setMinMaxTLS(tlsID)
client.TLS.CipherSuites = []uint16{id}
client.run()
}
// TODO test other kex methods besides X25519, like MTI secp256r1 // TODO test other kex methods besides X25519, like MTI secp256r1
// TODO limit supported groups? // TODO limit supported groups?