From 798661a0cfc29141a92814c13ca3ee084fd23a35 Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Thu, 18 Oct 2018 20:44:23 -0700 Subject: [PATCH 1/2] kex-spurious-failures branch: -Modified KyberDialSetup()/KyberAcceptSetup() to use []byte for reading/writing ciphertext to avoid errors caused by leading zero bytes (big.Int can't explicitly represent these) -TODO: Consider the same for HerraduraKEx HKexDialSetup()/HKexAcceptSetup() --- hkexnet/hkexnet.go | 43 ++++++++++++++++++++++--------------------- hkexsh/hkexsh.go | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/hkexnet/hkexnet.go b/hkexnet/hkexnet.go index 35387cc..c6a97e6 100644 --- a/hkexnet/hkexnet.go +++ b/hkexnet/hkexnet.go @@ -277,26 +277,26 @@ func KyberDialSetup(c net.Conn, hc *Conn) (err error) { } // Alice, step 2: Send the public key to Bob - fmt.Fprintf(c, "0x%x\n%08x:%08x\n", alicePublicKey.Bytes(), + fmt.Fprintf(c, "0x%x\n0x%x:0x%x\n", alicePublicKey.Bytes(), hc.cipheropts, hc.opts) // [Bob, step 1-3], from which we read cipher text - b := big.NewInt(0) - _, err = fmt.Fscanln(c, b) - if err != nil { - return err - } - log.Printf("[Got server ciphertext:0x%x]\n", b.Bytes()) + cipherB := make([]byte, 4096) + fmt.Fscanf(c, "0x%x\n", &cipherB) + //if err != nil { + // return err + //} + log.Printf("[Got server ciphertext[]:%v]\n", cipherB) // Read cipheropts, session opts - _, err = fmt.Fscanf(c, "%08x:%08x\n", + _, err = fmt.Fscanf(c, "0x%x:0x%x\n", &hc.cipheropts, &hc.opts) if err != nil { return err } // Alice, step 3: Decrypt the KEM cipher text. - aliceSharedSecret := alicePrivateKey.KEMDecrypt(b.Bytes()) + aliceSharedSecret := alicePrivateKey.KEMDecrypt(cipherB) log.Printf("[Derived sharedSecret:0x%x]\n", aliceSharedSecret) hc.r, hc.rm, err = hc.getStream(aliceSharedSecret) @@ -321,16 +321,16 @@ func HKExDialSetup(c net.Conn, hc *Conn) (err error) { // Send hkexnet.Conn parameters to remote side // d is value for Herradura key exchange - fmt.Fprintf(c, "0x%s\n%08x:%08x\n", h.D().Text(16), + fmt.Fprintf(c, "0x%s\n0x%x:0x%x\n", h.D().Text(16), hc.cipheropts, hc.opts) + // Read peer D over net.Conn (c) d := big.NewInt(0) _, err = fmt.Fscanln(c, d) if err != nil { return err } - // Read peer D over net.Conn (c) - _, err = fmt.Fscanf(c, "%08x:%08x\n", + _, err = fmt.Fscanf(c, "0x%x:0x%x\n", &hc.cipheropts, &hc.opts) if err != nil { return err @@ -355,7 +355,7 @@ func KyberAcceptSetup(c *net.Conn, hc *Conn) (err error) { if err != nil { return err } - _, err = fmt.Fscanf(*c, "%08x:%08x\n", + _, err = fmt.Fscanf(*c, "0x%x:0x%x\n", &hc.cipheropts, &hc.opts) log.Printf("[Got cipheropts, opts:%v, %v]", hc.cipheropts, hc.opts) if err != nil { @@ -385,8 +385,9 @@ func KyberAcceptSetup(c *net.Conn, hc *Conn) (err error) { panic(err) } - // Bob, step 3: Send the cipher text to Alice (Not shown). - fmt.Fprintf(*c, "0x%x\n%08x:%08x\n", cipherText, + // Bob, step 3: Send the cipher text to Alice. + //fmt.Println("cipherText:",cipherText) + fmt.Fprintf(*c, "0x%x\n0x%x:0x%x\n", cipherText, hc.cipheropts, hc.opts) log.Printf("[Derived sharedSecret:0x%x]\n", bobSharedSecret) @@ -418,7 +419,7 @@ func HKExAcceptSetup(c *net.Conn, hc *Conn) (err error) { if err != nil { return err } - _, err = fmt.Fscanf(*c, "%08x:%08x\n", + _, err = fmt.Fscanf(*c, "0x%x:0x%x\n", &hc.cipheropts, &hc.opts) log.Printf("[Got cipheropts, opts:%v, %v]", hc.cipheropts, hc.opts) if err != nil { @@ -431,7 +432,7 @@ func HKExAcceptSetup(c *net.Conn, hc *Conn) (err error) { log.Printf("**(s)** FA:%s\n", h.FA()) // Send D and cipheropts/conn_opts to peer - fmt.Fprintf(*c, "0x%s\n%08x:%08x\n", h.D().Text(16), + fmt.Fprintf(*c, "0x%s\n0x%x:0x%x\n", h.D().Text(16), hc.cipheropts, hc.opts) hc.r, hc.rm, err = hc.getStream(h.FA().Bytes()) @@ -490,7 +491,7 @@ func Dial(protocol string, ipport string, extensions ...string) (hc Conn, err er return Conn{}, nil } default: - return Conn{}, nil + return Conn{}, err } return } @@ -628,7 +629,7 @@ func (hl *HKExListener) Accept() (hc Conn, err error) { case KEX_HERRADURA2048: log.Printf("[Setting up for KEX_HERRADURA %d]\n", hc.kex) if HKExAcceptSetup(&c, &hc) != nil { - return Conn{}, nil + return Conn{}, err } case KEX_KYBER512: fallthrough @@ -637,10 +638,10 @@ func (hl *HKExListener) Accept() (hc Conn, err error) { case KEX_KYBER1024: log.Printf("[Setting up for KEX_KYBER %d]\n", hc.kex) if KyberAcceptSetup(&c, &hc) != nil { - return Conn{}, nil + return Conn{}, err } default: - return Conn{}, nil + return Conn{}, err } log.Println("[hc.Accept successful]") return diff --git a/hkexsh/hkexsh.go b/hkexsh/hkexsh.go index 88dc290..9600141 100755 --- a/hkexsh/hkexsh.go +++ b/hkexsh/hkexsh.go @@ -484,7 +484,7 @@ func main() { idx := strings.Index(string(ab), remoteHost) //fmt.Printf("auth entry idx:%d\n", idx) if idx >= 0 { - fmt.Fprintln(os.Stderr, "[authtoken]") + //fmt.Fprintln(os.Stderr, "[authtoken]") ab = ab[idx:] entries := strings.SplitN(string(ab), "\n", -1) //if len(entries) > 0 { From 3991fc50651242e3ff2cc95ca6200b6677c75ded Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Fri, 19 Oct 2018 13:51:57 -0700 Subject: [PATCH 2/2] Added keymat expansion for smallest KEX modes Signed-off-by: Russ Magee --- hkexnet/hkexchan.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hkexnet/hkexchan.go b/hkexnet/hkexchan.go index 543e86e..d007728 100644 --- a/hkexnet/hkexchan.go +++ b/hkexnet/hkexchan.go @@ -29,6 +29,27 @@ import ( _ "crypto/sha512" ) +// Expand keymat, if necessary, to a minimum of 2x(blocksize). +// Keymat is used for initial key and the IV, hence the 2x. +// This is occasionally necessary for smaller modes of KEX algorithms +// (eg., KEX_HERRADURA256); perhaps an indication these should be +// avoided in favour of larger modes. +func expandKeyMat(keymat []byte, blocksize int) []byte { + if len(keymat) < 2*blocksize { + halg := crypto.SHA256 + mc := halg.New() + if !halg.Available() { + log.Fatal("hash not available!") + } + _, _ = mc.Write(keymat) + var xpand []byte + xpand = mc.Sum(xpand) + keymat = append(keymat, xpand...) + log.Println("[NOTE: keymat short - applying key expansion using SHA256]") + } + return keymat +} + /* Support functionality to set up encryption after a channel has been negotiated via hkexnet.go */ @@ -43,6 +64,7 @@ func (hc Conn) getStream(keymat []byte) (rc cipher.Stream, mc hash.Hash, err err // is >= 2*cipher.BlockSize (enough for both key and iv) switch copts { case CAlgAES256: + keymat = expandKeyMat(keymat, aes.BlockSize) key = keymat[0:aes.BlockSize] block, err = aes.NewCipher(key) ivlen = aes.BlockSize @@ -51,6 +73,7 @@ func (hc Conn) getStream(keymat []byte) (rc cipher.Stream, mc hash.Hash, err err log.Printf("[cipher AES_256 (%d)]\n", copts) break case CAlgTwofish128: + keymat = expandKeyMat(keymat, twofish.BlockSize) key = keymat[0:twofish.BlockSize] block, err = twofish.NewCipher(key) ivlen = twofish.BlockSize @@ -59,6 +82,7 @@ func (hc Conn) getStream(keymat []byte) (rc cipher.Stream, mc hash.Hash, err err log.Printf("[cipher TWOFISH_128 (%d)]\n", copts) break case CAlgBlowfish64: + keymat = expandKeyMat(keymat, blowfish.BlockSize) key = keymat[0:blowfish.BlockSize] block, err = blowfish.NewCipher(key) ivlen = blowfish.BlockSize