It was unwittingly dropped from received connections, and may never have been set for initiated connections.
func (cl *Client) initiateHandshakes(c *connection, t *Torrent) (ok bool, err error) {
if c.headerEncrypted {
var rw io.ReadWriter
- rw, err = mse.InitiateHandshake(
+ rw, c.cryptoMethod, err = mse.InitiateHandshake(
struct {
io.Reader
io.Writer
}
}
headerEncrypted = true
- ret, err = mse.ReceiveHandshake(rw, skeys, func(provides mse.CryptoMethod) mse.CryptoMethod {
+ ret, cryptoMethod, err = mse.ReceiveHandshake(rw, skeys, func(provides mse.CryptoMethod) mse.CryptoMethod {
switch {
case policy.ForceEncryption:
return mse.CryptoMethodRC4
return newEncrypt(initer, h.s[:], h.skey)
}
-func (h *handshake) initerSteps() (ret io.ReadWriter, err error) {
+func (h *handshake) initerSteps() (ret io.ReadWriter, selected CryptoMethod, err error) {
h.postWrite(hash(req1, h.s[:]))
h.postWrite(xor(hash(req2, h.skey), hash(req3, h.s[:])))
buf := &bytes.Buffer{}
if err != nil {
return
}
- switch method & h.cryptoProvides {
+ selected = method & h.cryptoProvides
+ switch selected {
case CryptoMethodRC4:
ret = readWriter{r, &cipherWriter{e, h.conn, nil}}
case CryptoMethodPlaintext:
var ErrNoSecretKeyMatch = errors.New("no skey matched")
-func (h *handshake) receiverSteps() (ret io.ReadWriter, err error) {
+func (h *handshake) receiverSteps() (ret io.ReadWriter, chosen CryptoMethod, err error) {
// There is up to 512 bytes of padding, then the 20 byte hash.
err = readUntil(io.LimitReader(h.conn, 532), hash(req1, h.s[:]))
if err != nil {
return
}
cryptoProvidesCount.Add(strconv.FormatUint(uint64(provides), 16), 1)
- chosen := h.chooseMethod(provides)
+ chosen = h.chooseMethod(provides)
_, err = io.CopyN(ioutil.Discard, r, int64(padLen))
if err != nil {
return
return
}
-func (h *handshake) Do() (ret io.ReadWriter, err error) {
+func (h *handshake) Do() (ret io.ReadWriter, method CryptoMethod, err error) {
h.writeCond.L = &h.writeMu
h.writerCond.L = &h.writerMu
go h.writer()
return
}
if h.initer {
- ret, err = h.initerSteps()
+ ret, method, err = h.initerSteps()
} else {
- ret, err = h.receiverSteps()
+ ret, method, err = h.receiverSteps()
}
return
}
-func InitiateHandshake(rw io.ReadWriter, skey []byte, initialPayload []byte, cryptoProvides CryptoMethod) (ret io.ReadWriter, err error) {
+func InitiateHandshake(rw io.ReadWriter, skey []byte, initialPayload []byte, cryptoProvides CryptoMethod) (ret io.ReadWriter, method CryptoMethod, err error) {
h := handshake{
conn: rw,
initer: true,
return h.Do()
}
-func ReceiveHandshake(rw io.ReadWriter, skeys SecretKeyIter, selectCrypto CryptoSelector) (ret io.ReadWriter, err error) {
+func ReceiveHandshake(rw io.ReadWriter, skeys SecretKeyIter, selectCrypto CryptoSelector) (ret io.ReadWriter, method CryptoMethod, err error) {
h := handshake{
conn: rw,
initer: false,
_ "github.com/anacrolix/envpprof"
"github.com/bradfitz/iter"
+ "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
wg.Add(2)
go func() {
defer wg.Done()
- a, err := InitiateHandshake(a, []byte("yep"), ia, cryptoProvides)
- if err != nil {
- t.Fatal(err)
- return
- }
+ a, cm, err := InitiateHandshake(a, []byte("yep"), ia, cryptoProvides)
+ require.NoError(t, err)
+ assert.Equal(t, cryptoSelect(cryptoProvides), cm)
go a.Write([]byte(aData))
var msg [20]byte
}()
go func() {
defer wg.Done()
- b, err := ReceiveHandshake(b, sliceIter([][]byte{[]byte("nope"), []byte("yep"), []byte("maybe")}), cryptoSelect)
- if err != nil {
- t.Fatal(err)
- return
- }
+ b, cm, err := ReceiveHandshake(b, sliceIter([][]byte{[]byte("nope"), []byte("yep"), []byte("maybe")}), cryptoSelect)
+ require.NoError(t, err)
+ assert.Equal(t, cryptoSelect(cryptoProvides), cm)
go b.Write([]byte(bData))
// Need to be exact here, as there are several reads, and net.Pipe is
// most synchronous.
func TestReceiveRandomData(t *testing.T) {
tr := trackReader{rand.Reader, 0}
- _, err := ReceiveHandshake(readWriter{&tr, ioutil.Discard}, nil, DefaultCryptoSelector)
+ _, _, err := ReceiveHandshake(readWriter{&tr, ioutil.Discard}, nil, DefaultCryptoSelector)
// No skey matches
require.Error(t, err)
// Establishing S, and then reading the maximum padding for giving up on
go func() {
defer ac.Close()
defer wg.Done()
- rw, err := InitiateHandshake(ac, []byte("cats"), ia, crypto)
+ rw, _, err := InitiateHandshake(ac, []byte("cats"), ia, crypto)
require.NoError(t, err)
require.NoError(t, readAndWrite(rw, ar, a))
}()
func() {
defer bc.Close()
- rw, err := ReceiveHandshake(bc, sliceIter([][]byte{[]byte("cats")}), func(CryptoMethod) CryptoMethod { return crypto })
+ rw, _, err := ReceiveHandshake(bc, sliceIter([][]byte{[]byte("cats")}), func(CryptoMethod) CryptoMethod { return crypto })
require.NoError(t, err)
require.NoError(t, readAndWrite(rw, br, b))
}()