Skip to content

Commit 1b76d66

Browse files
bremlhanwen
authored andcommitted
ssh: fix data race in dh group exchange sha256
Fixes golang/go#37607 Change-Id: Iedf6522ec9b9a676ac51c054407a6aef894885f5 GitHub-Last-Rev: 8cb2460 GitHub-Pull-Request: #126 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/222078 Reviewed-by: Han-Wen Nienhuys <[email protected]> Run-TryBot: Han-Wen Nienhuys <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent f7b0055 commit 1b76d66

File tree

2 files changed

+42
-27
lines changed

2 files changed

+42
-27
lines changed

ssh/kex.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ func (gex *dhGEXSHA) diffieHellman(theirPublic, myPrivate *big.Int) (*big.Int, e
572572
return new(big.Int).Exp(theirPublic, myPrivate, gex.p), nil
573573
}
574574

575-
func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
575+
func (gex dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
576576
// Send GexRequest
577577
kexDHGexRequest := kexDHGexRequestMsg{
578578
MinBits: dhGroupExchangeMinimumBits,
@@ -677,7 +677,7 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
677677
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
678678
//
679679
// This is a minimal implementation to satisfy the automated tests.
680-
func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
680+
func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv Signer) (result *kexResult, err error) {
681681
// Receive GexRequest
682682
packet, err := c.readPacket()
683683
if err != nil {

ssh/kex_test.go

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,57 @@ package ssh
99
import (
1010
"crypto/rand"
1111
"reflect"
12+
"sync"
1213
"testing"
1314
)
1415

16+
// Runs multiple key exchanges concurrent to detect potential data races with
17+
// kex obtained from the global kexAlgoMap.
18+
// This test needs to be executed using the race detector in order to detect
19+
// race conditions.
1520
func TestKexes(t *testing.T) {
1621
type kexResultErr struct {
1722
result *kexResult
1823
err error
1924
}
2025

2126
for name, kex := range kexAlgoMap {
22-
a, b := memPipe()
27+
t.Run(name, func(t *testing.T) {
28+
wg := sync.WaitGroup{}
29+
for i := 0; i < 3; i++ {
30+
wg.Add(1)
31+
go func() {
32+
defer wg.Done()
33+
a, b := memPipe()
2334

24-
s := make(chan kexResultErr, 1)
25-
c := make(chan kexResultErr, 1)
26-
var magics handshakeMagics
27-
go func() {
28-
r, e := kex.Client(a, rand.Reader, &magics)
29-
a.Close()
30-
c <- kexResultErr{r, e}
31-
}()
32-
go func() {
33-
r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
34-
b.Close()
35-
s <- kexResultErr{r, e}
36-
}()
35+
s := make(chan kexResultErr, 1)
36+
c := make(chan kexResultErr, 1)
37+
var magics handshakeMagics
38+
go func() {
39+
r, e := kex.Client(a, rand.Reader, &magics)
40+
a.Close()
41+
c <- kexResultErr{r, e}
42+
}()
43+
go func() {
44+
r, e := kex.Server(b, rand.Reader, &magics, testSigners["ecdsa"])
45+
b.Close()
46+
s <- kexResultErr{r, e}
47+
}()
3748

38-
clientRes := <-c
39-
serverRes := <-s
40-
if clientRes.err != nil {
41-
t.Errorf("client: %v", clientRes.err)
42-
}
43-
if serverRes.err != nil {
44-
t.Errorf("server: %v", serverRes.err)
45-
}
46-
if !reflect.DeepEqual(clientRes.result, serverRes.result) {
47-
t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
48-
}
49+
clientRes := <-c
50+
serverRes := <-s
51+
if clientRes.err != nil {
52+
t.Errorf("client: %v", clientRes.err)
53+
}
54+
if serverRes.err != nil {
55+
t.Errorf("server: %v", serverRes.err)
56+
}
57+
if !reflect.DeepEqual(clientRes.result, serverRes.result) {
58+
t.Errorf("kex %q: mismatch %#v, %#v", name, clientRes.result, serverRes.result)
59+
}
60+
}()
61+
}
62+
wg.Wait()
63+
})
4964
}
5065
}

0 commit comments

Comments
 (0)