From 5fd6174b77647f847a6e6db1cb7d5276747fcd39 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 5 May 2016 11:44:24 +0300 Subject: [PATCH] crypto/rand does not guarantee full read at once --- src/cypherpunks.ru/govpn/aont/aont_test.go | 7 ++++--- .../govpn/cmd/govpn-verifier/main.go | 3 ++- src/cypherpunks.ru/govpn/cnw/cnw_test.go | 11 ++++++----- src/cypherpunks.ru/govpn/egd.go | 14 ++------------ src/cypherpunks.ru/govpn/encless.go | 4 +++- src/cypherpunks.ru/govpn/encless_test.go | 12 ++++++------ src/cypherpunks.ru/govpn/handshake.go | 12 ++++++------ 7 files changed, 29 insertions(+), 34 deletions(-) diff --git a/src/cypherpunks.ru/govpn/aont/aont_test.go b/src/cypherpunks.ru/govpn/aont/aont_test.go index 93b7db5..0ef140c 100644 --- a/src/cypherpunks.ru/govpn/aont/aont_test.go +++ b/src/cypherpunks.ru/govpn/aont/aont_test.go @@ -21,6 +21,7 @@ package aont import ( "bytes" "crypto/rand" + "io" "testing" "testing/quick" ) @@ -30,7 +31,7 @@ var ( ) func init() { - rand.Read(testKey[:]) + io.ReadFull(rand.Reader, testKey[:]) } func TestSymmetric(t *testing.T) { @@ -80,7 +81,7 @@ func TestTampered(t *testing.T) { func BenchmarkEncode(b *testing.B) { data := make([]byte, 128) - rand.Read(data) + io.ReadFull(rand.Reader, data) b.ResetTimer() for i := 0; i < b.N; i++ { Encode(testKey, data) @@ -89,7 +90,7 @@ func BenchmarkEncode(b *testing.B) { func BenchmarkDecode(b *testing.B) { data := make([]byte, 128) - rand.Read(data) + io.ReadFull(rand.Reader, data) encoded, _ := Encode(testKey, data) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go b/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go index bdea079..d5dcfa5 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go @@ -23,6 +23,7 @@ import ( "bytes" "flag" "fmt" + "io" "log" "cypherpunks.ru/govpn" @@ -53,7 +54,7 @@ func main() { } if *verifier == "" { id := new([govpn.IDSize]byte) - if _, err := govpn.Rand.Read(id[:]); err != nil { + if _, err = io.ReadFull(govpn.Rand, id[:]); err != nil { log.Fatalln(err) } pid := govpn.PeerId(*id) diff --git a/src/cypherpunks.ru/govpn/cnw/cnw_test.go b/src/cypherpunks.ru/govpn/cnw/cnw_test.go index 24cf452..cbb28e9 100644 --- a/src/cypherpunks.ru/govpn/cnw/cnw_test.go +++ b/src/cypherpunks.ru/govpn/cnw/cnw_test.go @@ -22,6 +22,7 @@ import ( "bytes" "crypto/rand" "encoding/binary" + "io" "testing" "testing/quick" ) @@ -31,7 +32,7 @@ var ( ) func init() { - rand.Read(testKey[:]) + io.ReadFull(rand.Reader, testKey[:]) } func TestSymmetric(t *testing.T) { @@ -66,8 +67,8 @@ func TestSmallSize(t *testing.T) { func BenchmarkChaff(b *testing.B) { nonce := make([]byte, 8) data := make([]byte, 16) - rand.Read(nonce) - rand.Read(data) + io.ReadFull(rand.Reader, nonce) + io.ReadFull(rand.Reader, data) b.ResetTimer() for i := 0; i < b.N; i++ { Chaff(testKey, nonce, data) @@ -77,8 +78,8 @@ func BenchmarkChaff(b *testing.B) { func BenchmarkWinnow(b *testing.B) { nonce := make([]byte, 8) data := make([]byte, 16) - rand.Read(nonce) - rand.Read(data) + io.ReadFull(rand.Reader, nonce) + io.ReadFull(rand.Reader, data) chaffed := Chaff(testKey, nonce, data) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/src/cypherpunks.ru/govpn/egd.go b/src/cypherpunks.ru/govpn/egd.go index 04ec87b..3d0b791 100644 --- a/src/cypherpunks.ru/govpn/egd.go +++ b/src/cypherpunks.ru/govpn/egd.go @@ -20,7 +20,6 @@ package govpn import ( "crypto/rand" - "errors" "io" "net" ) @@ -37,18 +36,9 @@ func (egdPath EGDRand) Read(b []byte) (int, error) { if err != nil { return 0, err } + defer conn.Close() conn.Write([]byte{0x02, byte(len(b))}) - read, err := conn.Read(b) - if err != nil { - conn.Close() - return read, err - } - if read != len(b) { - conn.Close() - return read, errors.New("Got less bytes than expected from EGD") - } - conn.Close() - return read, nil + return io.ReadFull(conn, b) } func EGDInit(path string) { diff --git a/src/cypherpunks.ru/govpn/encless.go b/src/cypherpunks.ru/govpn/encless.go index 30eb4a5..f9d9bbf 100644 --- a/src/cypherpunks.ru/govpn/encless.go +++ b/src/cypherpunks.ru/govpn/encless.go @@ -19,6 +19,8 @@ along with this program. If not, see . package govpn import ( + "io" + "cypherpunks.ru/govpn/aont" "cypherpunks.ru/govpn/cnw" ) @@ -36,7 +38,7 @@ const ( func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) { r := new([aont.RSize]byte) var err error - if _, err = Rand.Read(r[:]); err != nil { + if _, err = io.ReadFull(Rand, r[:]); err != nil { return nil, err } aonted, err := aont.Encode(r, in) diff --git a/src/cypherpunks.ru/govpn/encless_test.go b/src/cypherpunks.ru/govpn/encless_test.go index 20b0df6..1f9fece 100644 --- a/src/cypherpunks.ru/govpn/encless_test.go +++ b/src/cypherpunks.ru/govpn/encless_test.go @@ -20,8 +20,8 @@ package govpn import ( "bytes" - "crypto/rand" "encoding/binary" + "io" "testing" "testing/quick" ) @@ -31,7 +31,7 @@ var ( ) func init() { - rand.Read(testKey[:]) + io.ReadFull(Rand, testKey[:]) } func TestEnclessSymmetric(t *testing.T) { @@ -56,8 +56,8 @@ func TestEnclessSymmetric(t *testing.T) { func BenchmarkEnclessEncode(b *testing.B) { nonce := make([]byte, 8) data := make([]byte, 128) - rand.Read(nonce) - rand.Read(data) + io.ReadFull(Rand, nonce) + io.ReadFull(Rand, data) b.ResetTimer() for i := 0; i < b.N; i++ { EnclessEncode(testKey, nonce, data) @@ -67,8 +67,8 @@ func BenchmarkEnclessEncode(b *testing.B) { func BenchmarkEnclessDecode(b *testing.B) { nonce := make([]byte, 8) data := make([]byte, 128) - rand.Read(nonce) - rand.Read(data) + io.ReadFull(Rand, nonce) + io.ReadFull(Rand, data) encoded, _ := EnclessEncode(testKey, nonce, data) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/src/cypherpunks.ru/govpn/handshake.go b/src/cypherpunks.ru/govpn/handshake.go index 4f080eb..9d5f688 100644 --- a/src/cypherpunks.ru/govpn/handshake.go +++ b/src/cypherpunks.ru/govpn/handshake.go @@ -102,7 +102,7 @@ func dhKeypairGen() (*[32]byte, *[32]byte) { repr := new([32]byte) reprFound := false for !reprFound { - if _, err := Rand.Read(priv[:]); err != nil { + if _, err := io.ReadFull(Rand, priv[:]); err != nil { log.Fatalln("Error reading random for DH private key:", err) } reprFound = extra25519.ScalarBaseMult(pub, repr, priv) @@ -154,7 +154,7 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake { state.dhPriv, dhPubRepr = dhKeypairGen() state.rNonce = new([RSize]byte) - if _, err := Rand.Read(state.rNonce[:]); err != nil { + if _, err := io.ReadFull(Rand, state.rNonce[:]); err != nil { log.Fatalln("Error reading random for nonce:", err) } var enc []byte @@ -238,11 +238,11 @@ func (h *Handshake) Server(data []byte) *Peer { // Generate R* and encrypt them h.rServer = new([RSize]byte) - if _, err = Rand.Read(h.rServer[:]); err != nil { + if _, err = io.ReadFull(Rand, h.rServer[:]); err != nil { log.Fatalln("Error reading random for R:", err) } h.sServer = new([SSize]byte) - if _, err = Rand.Read(h.sServer[:]); err != nil { + if _, err = io.ReadFull(Rand, h.sServer[:]); err != nil { log.Fatalln("Error reading random for S:", err) } var encRs []byte @@ -406,11 +406,11 @@ func (h *Handshake) Client(data []byte) *Peer { // Generate R* and signature and encrypt them h.rClient = new([RSize]byte) - if _, err = Rand.Read(h.rClient[:]); err != nil { + if _, err = io.ReadFull(Rand, h.rClient[:]); err != nil { log.Fatalln("Error reading random for R:", err) } h.sClient = new([SSize]byte) - if _, err = Rand.Read(h.sClient[:]); err != nil { + if _, err = io.ReadFull(Rand, h.sClient[:]); err != nil { log.Fatalln("Error reading random for S:", err) } sign := ed25519.Sign(h.Conf.DSAPriv, h.key[:]) -- 2.44.0