X-Git-Url: http://www.git.cypherpunks.ru/?p=govpn.git;a=blobdiff_plain;f=src%2Fcypherpunks.ru%2Fgovpn%2Fidentity.go;h=d738c5563e091179bd1e1fa287fb1bbcbd6ef1d9;hp=f85631b01839639b8bf981572f4c8b6db106c984;hb=8deaf99f98548064f51a3fe5a163456257c089bb;hpb=68e0c647218f529318c07eb7be85f82034d9904a diff --git a/src/cypherpunks.ru/govpn/identity.go b/src/cypherpunks.ru/govpn/identity.go index f85631b..d738c55 100644 --- a/src/cypherpunks.ru/govpn/identity.go +++ b/src/cypherpunks.ru/govpn/identity.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,11 +22,12 @@ import ( "crypto/subtle" "encoding/base64" "encoding/binary" + "hash" "log" "sync" "time" - "golang.org/x/crypto/xtea" + "golang.org/x/crypto/blake2b" ) const ( @@ -43,42 +44,46 @@ func (id PeerId) MarshalJSON() ([]byte, error) { return []byte(`"` + id.String() + `"`), nil } -type CipherAndTimeSync struct { - c *xtea.Cipher - t int +type MACAndTimeSync struct { + mac hash.Hash + ts int + l sync.Mutex } -type CipherCache struct { - c map[PeerId]*CipherAndTimeSync - l sync.RWMutex +type MACCache struct { + cache map[PeerId]*MACAndTimeSync + l sync.RWMutex } -func NewCipherCache() *CipherCache { - return &CipherCache{c: make(map[PeerId]*CipherAndTimeSync)} +func NewMACCache() *MACCache { + return &MACCache{cache: make(map[PeerId]*MACAndTimeSync)} } -// Remove disappeared keys, add missing ones with initialized ciphers. -func (cc *CipherCache) Update(peers *map[PeerId]*PeerConf) { - cc.l.Lock() - for pid, _ := range cc.c { +// Remove disappeared keys, add missing ones with initialized MACs. +func (mc *MACCache) Update(peers *map[PeerId]*PeerConf) { + mc.l.Lock() + for pid, _ := range mc.cache { if _, exists := (*peers)[pid]; !exists { log.Println("Cleaning key:", pid) - delete(cc.c, pid) + delete(mc.cache, pid) } } for pid, pc := range *peers { - if _, exists := cc.c[pid]; exists { - cc.c[pid].t = pc.TimeSync + if _, exists := mc.cache[pid]; exists { + mc.cache[pid].ts = pc.TimeSync } else { log.Println("Adding key", pid) - cipher, err := xtea.NewCipher(pid[:]) + mac, err := blake2b.New256(pid[:]) if err != nil { panic(err) } - cc.c[pid] = &CipherAndTimeSync{cipher, pc.TimeSync} + mc.cache[pid] = &MACAndTimeSync{ + mac: mac, + ts: pc.TimeSync, + } } } - cc.l.Unlock() + mc.l.Unlock() } // If timeSync > 0, then XOR timestamp with the data. @@ -93,24 +98,29 @@ func AddTimeSync(ts int, data []byte) { } } -// Try to find peer's identity (that equals to an encryption key) +// Try to find peer's identity (that equals to MAC) // by taking first blocksize sized bytes from data at the beginning // as plaintext and last bytes as cyphertext. -func (cc *CipherCache) Find(data []byte) *PeerId { - if len(data) < xtea.BlockSize*2 { +func (mc *MACCache) Find(data []byte) *PeerId { + if len(data) < 8*2 { return nil } - buf := make([]byte, xtea.BlockSize) - cc.l.RLock() - for pid, ct := range cc.c { - ct.c.Decrypt(buf, data[len(data)-xtea.BlockSize:]) - AddTimeSync(ct.t, buf) - if subtle.ConstantTimeCompare(buf, data[:xtea.BlockSize]) == 1 { + buf := make([]byte, 8) + mc.l.RLock() + for pid, mt := range mc.cache { + copy(buf, data) + AddTimeSync(mt.ts, buf) + mt.l.Lock() + mt.mac.Reset() + mt.mac.Write(buf) + sum := mt.mac.Sum(nil) + mt.l.Unlock() + if subtle.ConstantTimeCompare(sum[len(sum)-8:], data[len(data)-8:]) == 1 { ppid := PeerId(pid) - cc.l.RUnlock() + mc.l.RUnlock() return &ppid } } - cc.l.RUnlock() + mc.l.RUnlock() return nil }