Browse Source

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
v1.2.3
Kris Kwiatkowski 6 years ago
committed by Kris Kwiatkowski
parent
commit
76231e7564
5 changed files with 62 additions and 42 deletions
  1. +2
    -2
      13.go
  2. +1
    -1
      _dev/boring/Dockerfile
  3. +1
    -1
      _dev/boring/server.sh
  4. +13
    -2
      _dev/interop_test_runner
  5. +45
    -36
      _dev/tris-testclient/client.go

+ 2
- 2
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 {


+ 1
- 1
_dev/boring/Dockerfile 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


+ 1
- 1
_dev/boring/server.sh 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 &




+ 13
- 2
_dev/interop_test_runner 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):


+ 45
- 36
_dev/tris-testclient/client.go 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)
client.TLS.CipherSuites = []uint16{tls.TLS_CHACHA20_POLY1305_SHA256}
client.run()

client.setMinMaxTLS(tls.VersionTLS13)
client.TLS.CipherSuites = []uint16{tls.TLS_AES_128_GCM_SHA256}
client.run()
// Set requested DH groups
client.TLS.CurvePreferences = []tls.CurveID{}
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)
client.TLS.CipherSuites = []uint16{tls.TLS_AES_256_GCM_SHA384}
client.run()
// Perform TLS handshake with each each requested CipherSuite
tlsID, err := getIDByName(tlsVersionToName, tls_version)
if err != nil {
panic("Unknown TLS version")
}
for _, cn := range strings.Split(named_ciphers, ":") {
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?


Loading…
Cancel
Save