diff options
author | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2017-06-23 13:41:59 +0200 |
---|---|---|
committer | Mathias Hall-Andersen <mathias@hall-andersen.dk> | 2017-06-23 13:41:59 +0200 |
commit | 50aeefcb5198d99777e19f9a0100fe74af630dfb (patch) | |
tree | 5e8924cde01e586fcb1f7168946bee46528d70c9 /src/noise_protocol.go | |
parent | 1868d15914d6cd7cd57b90b7644b008ec16361b9 (diff) |
Beginning work noise handshake
Diffstat (limited to 'src/noise_protocol.go')
-rw-r--r-- | src/noise_protocol.go | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/noise_protocol.go b/src/noise_protocol.go new file mode 100644 index 0000000..e7c8774 --- /dev/null +++ b/src/noise_protocol.go @@ -0,0 +1,179 @@ +package main + +import ( + "errors" + "golang.org/x/crypto/blake2s" + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/poly1305" + "sync" +) + +const ( + HandshakeInitialCreated = iota + HandshakeInitialConsumed + HandshakeResponseCreated +) + +const ( + NoiseConstruction = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s" + WGIdentifier = "WireGuard v1 zx2c4 Jason@zx2c4.com" + WGLabelMAC1 = "mac1----" + WGLabelCookie = "cookie--" +) + +const ( + MessageInitalType = 1 + MessageResponseType = 2 + MessageCookieResponseType = 3 + MessageTransportType = 4 +) + +type MessageInital struct { + Type uint32 + Sender uint32 + Ephemeral NoisePublicKey + Static [NoisePublicKeySize + poly1305.TagSize]byte + Timestamp [TAI64NSize + poly1305.TagSize]byte + Mac1 [blake2s.Size128]byte + Mac2 [blake2s.Size128]byte +} + +type MessageResponse struct { + Type uint32 + Sender uint32 + Reciever uint32 + Ephemeral NoisePublicKey + Empty [poly1305.TagSize]byte + Mac1 [blake2s.Size128]byte + Mac2 [blake2s.Size128]byte +} + +type MessageTransport struct { + Type uint32 + Reciever uint32 + Counter uint64 + Content []byte +} + +type Handshake struct { + lock sync.Mutex + state int + chainKey [blake2s.Size]byte // chain key + hash [blake2s.Size]byte // hash value + staticStatic NoisePublicKey // precomputed DH(S_i, S_r) + ephemeral NoisePrivateKey // ephemeral secret key + remoteIndex uint32 // index for sending + device *Device + peer *Peer +} + +var ( + ZeroNonce [chacha20poly1305.NonceSize]byte + InitalChainKey [blake2s.Size]byte + InitalHash [blake2s.Size]byte +) + +func init() { + InitalChainKey = blake2s.Sum256([]byte(NoiseConstruction)) + InitalHash = blake2s.Sum256(append(InitalChainKey[:], []byte(WGIdentifier)...)) +} + +func (h *Handshake) Precompute() { + h.staticStatic = h.device.privateKey.sharedSecret(h.peer.publicKey) +} + +func (h *Handshake) ConsumeMessageResponse(msg *MessageResponse) { + +} + +func (h *Handshake) addHash(data []byte) { + h.hash = addToHash(h.hash, data) +} + +func (h *Handshake) addChain(data []byte) { + h.chainKey = addToChainKey(h.chainKey, data) +} + +func (h *Handshake) CreateMessageInital() (*MessageInital, error) { + h.lock.Lock() + defer h.lock.Unlock() + + // reset handshake + + var err error + h.ephemeral, err = newPrivateKey() + if err != nil { + return nil, err + } + h.chainKey = InitalChainKey + h.hash = addToHash(InitalHash, h.device.publicKey[:]) + + // create ephemeral key + + var msg MessageInital + msg.Type = MessageInitalType + msg.Sender = h.device.NewID(h) + msg.Ephemeral = h.ephemeral.publicKey() + h.chainKey = addToChainKey(h.chainKey, msg.Ephemeral[:]) + h.hash = addToHash(h.hash, msg.Ephemeral[:]) + + // encrypt long-term "identity key" + + func() { + var key [chacha20poly1305.KeySize]byte + ss := h.ephemeral.sharedSecret(h.peer.publicKey) + h.chainKey, key = KDF2(h.chainKey[:], ss[:]) + aead, _ := chacha20poly1305.New(key[:]) + aead.Seal(msg.Static[:0], ZeroNonce[:], h.device.publicKey[:], nil) + }() + h.addHash(msg.Static[:]) + + // encrypt timestamp + + timestamp := Timestamp() + func() { + var key [chacha20poly1305.KeySize]byte + h.chainKey, key = KDF2(h.chainKey[:], h.staticStatic[:]) + aead, _ := chacha20poly1305.New(key[:]) + aead.Seal(msg.Timestamp[:0], ZeroNonce[:], timestamp[:], nil) + }() + h.addHash(msg.Timestamp[:]) + h.state = HandshakeInitialCreated + return &msg, nil +} + +func (h *Handshake) ConsumeMessageInitial(msg *MessageInital) error { + if msg.Type != MessageInitalType { + panic(errors.New("bug: invalid inital message type")) + } + + hash := addToHash(InitalHash, h.device.publicKey[:]) + chainKey := addToChainKey(InitalChainKey, msg.Ephemeral[:]) + hash = addToHash(hash, msg.Ephemeral[:]) + + // + + ephemeral, err := newPrivateKey() + if err != nil { + return err + } + + // update handshake state + + h.lock.Lock() + defer h.lock.Unlock() + + h.hash = hash + h.chainKey = chainKey + h.remoteIndex = msg.Sender + h.ephemeral = ephemeral + h.state = HandshakeInitialConsumed + + return nil + +} + +func (h *Handshake) CreateMessageResponse() []byte { + + return nil +} |