]> Cypherpunks.ru repositories - govpn.git/blob - src/govpn/identify.go
Use Argon2d PHC winner instead of PBKDF2
[govpn.git] / src / govpn / identify.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package govpn
20
21 import (
22         "crypto/subtle"
23         "encoding/hex"
24         "log"
25         "sync"
26
27         "golang.org/x/crypto/xtea"
28 )
29
30 const (
31         IDSize = 128 / 8
32 )
33
34 type PeerId [IDSize]byte
35
36 func (id PeerId) String() string {
37         return hex.EncodeToString(id[:])
38 }
39
40 type CipherCache struct {
41         c map[PeerId]*xtea.Cipher
42         l sync.RWMutex
43 }
44
45 func NewCipherCache(peerIds []PeerId) CipherCache {
46         cc := CipherCache{c: make(map[PeerId]*xtea.Cipher, len(peerIds))}
47         cc.Update(peerIds)
48         return cc
49 }
50
51 // Remove disappeared keys, add missing ones with initialized ciphers.
52 func (cc CipherCache) Update(peerIds []PeerId) {
53         available := make(map[PeerId]struct{})
54         for _, peerId := range peerIds {
55                 available[peerId] = struct{}{}
56         }
57         cc.l.Lock()
58         for k, _ := range cc.c {
59                 if _, exists := available[k]; !exists {
60                         log.Println("Cleaning key:", k)
61                         delete(cc.c, k)
62                 }
63         }
64         for peerId, _ := range available {
65                 if _, exists := cc.c[peerId]; !exists {
66                         log.Println("Adding key", peerId)
67                         cipher, err := xtea.NewCipher(peerId[:])
68                         if err != nil {
69                                 panic(err)
70                         }
71                         cc.c[peerId] = cipher
72                 }
73         }
74         cc.l.Unlock()
75 }
76
77 // Try to find peer's identity (that equals to an encryption key)
78 // by taking first blocksize sized bytes from data at the beginning
79 // as plaintext and last bytes as cyphertext.
80 func (cc CipherCache) Find(data []byte) *PeerId {
81         if len(data) < xtea.BlockSize*2 {
82                 return nil
83         }
84         buf := make([]byte, xtea.BlockSize)
85         cc.l.RLock()
86         for pid, cipher := range cc.c {
87                 cipher.Decrypt(buf, data[len(data)-xtea.BlockSize:])
88                 if subtle.ConstantTimeCompare(buf, data[:xtea.BlockSize]) == 1 {
89                         ppid := PeerId(pid)
90                         cc.l.RUnlock()
91                         return &ppid
92                 }
93         }
94         cc.l.RUnlock()
95         return nil
96 }