Beispiel #1
1
// Chaff the data. noncePrfx is 64-bit nonce. Output data will be much
// larger: 256 bytes for each input byte.
func Chaff(authKey *[32]byte, noncePrfx, in []byte) []byte {
	out := make([]byte, len(in)*EnlargeFactor)
	keys := make([]byte, 8*64)
	nonce := make([]byte, 24)
	copy(nonce[:8], noncePrfx)
	var i int
	var v byte
	tag := new([16]byte)
	macKey := new([32]byte)
	for n, b := range in {
		binary.BigEndian.PutUint64(nonce[16:], uint64(n))
		salsa20.XORKeyStream(keys, keys, nonce, authKey)
		for i = 0; i < 8; i++ {
			v = (b >> uint8(i)) & 1
			copy(macKey[:], keys[64*i:64*i+32])
			if v == 0 {
				poly1305.Sum(tag, []byte("1"), macKey)
			} else {
				poly1305.Sum(tag, []byte("0"), macKey)
			}
			copy(out[16*(n*16+i*2):], tag[:])
			copy(macKey[:], keys[64*i+32:64*i+64])
			if v == 1 {
				poly1305.Sum(tag, []byte("1"), macKey)
			} else {
				poly1305.Sum(tag, []byte("0"), macKey)
			}
			copy(out[16*(n*16+i*2+1):], tag[:])
		}
		zero(keys)
	}
	zero(macKey[:])
	return out
}
Beispiel #2
0
// Start handshake's procedure from the client. It is the entry point
// for starting the handshake procedure. // First handshake packet
// will be sent immediately.
func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
	state := NewHandshake(addr, conn, conf)
	var dhPubRepr *[32]byte
	state.dhPriv, dhPubRepr = dhKeypairGen()

	state.rNonce = new([RSize]byte)
	if _, err := Rand.Read(state.rNonce[:]); err != nil {
		log.Fatalln("Error reading random for nonce:", err)
	}
	var enc []byte
	if conf.Noise {
		enc = make([]byte, conf.MTU-xtea.BlockSize-RSize)
	} else {
		enc = make([]byte, 32)
	}
	copy(enc, dhPubRepr[:])
	if conf.Encless {
		var err error
		enc, err = EnclessEncode(state.dsaPubH, state.rNonce[:], enc)
		if err != err {
			panic(err)
		}
	} else {
		salsa20.XORKeyStream(enc, enc, state.rNonce[:], state.dsaPubH)
	}
	data := append(state.rNonce[:], enc...)
	data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[:])...)
	state.conn.Write(data)
	return state
}
Beispiel #3
0
func (session *CryptoSession) Encrypt(plaintext string) []byte {
	in := make([]byte, 64)
	copy(in, []byte(plaintext))
	out := make([]byte, 64)
	salsa20.XORKeyStream(out, in, Session.nonce, Session.sessionKey)
	return out
}
Beispiel #4
0
func (sr *Salsa20Rand) fill() {
	var nonce [8]byte
	binary.BigEndian.PutUint64(nonce[:], sr.nonce)
	sr.nonce += 1

	salsa20.XORKeyStream(sr.buffer, sr.zeroes, nonce[:], &sr.key)
	sr.bufferOffset = 0
}
Beispiel #5
0
// Salsa20 cipher
func BenchmarkSalsa20_1K(b *testing.B) {
	var key [32]byte
	var nonce [8]byte
	size := 1024
	b.SetBytes(int64(size))
	for i := 0; i < b.N; i++ {
		salsa20.XORKeyStream(buf[:size], buf[:size], nonce[:], &key)
	}
}
Beispiel #6
0
// Winnow the data.
func Winnow(authKey *[32]byte, noncePrfx, in []byte) ([]byte, error) {
	if len(in)%EnlargeFactor != 0 {
		return nil, errors.New("Invalid data size")
	}
	out := make([]byte, len(in)/EnlargeFactor)
	keys := make([]byte, 8*64)
	nonce := make([]byte, 24)
	copy(nonce[:8], noncePrfx)
	var i int
	var v byte
	tag := new([16]byte)
	macKey := new([32]byte)
	defer zero(macKey[:])
	var is01 bool
	var is00 bool
	var is11 bool
	var is10 bool
	for n := 0; n < len(out); n++ {
		binary.BigEndian.PutUint64(nonce[16:], uint64(n))
		salsa20.XORKeyStream(keys, keys, nonce, authKey)
		v = 0
		for i = 0; i < 8; i++ {
			copy(macKey[:], keys[64*i:64*i+32])
			poly1305.Sum(tag, []byte("1"), macKey)
			is01 = subtle.ConstantTimeCompare(
				tag[:],
				in[16*(n*16+i*2):16*(n*16+i*2+1)],
			) == 1
			poly1305.Sum(tag, []byte("0"), macKey)
			is00 = subtle.ConstantTimeCompare(
				tag[:],
				in[16*(n*16+i*2):16*(n*16+i*2+1)],
			) == 1
			copy(macKey[:], keys[64*i+32:64*i+64])
			poly1305.Sum(tag, []byte("1"), macKey)
			is11 = subtle.ConstantTimeCompare(
				tag[:],
				in[16*(n*16+i*2+1):16*(n*16+i*2+2)],
			) == 1
			poly1305.Sum(tag, []byte("0"), macKey)
			is10 = subtle.ConstantTimeCompare(
				tag[:],
				in[16*(n*16+i*2+1):16*(n*16+i*2+2)],
			) == 1
			if !((is01 && is10) || (is00 && is11)) {
				zero(keys)
				return nil, errors.New("Invalid authenticator received")
			}
			if is11 {
				v = v | 1<<uint8(i)
			}
		}
		out[n] = v
		zero(keys)
	}
	return out, nil
}
Beispiel #7
0
// Process incoming UDP packet.
// ConnListen'es synchronization channel used to tell him that he is
// free to receive new packets. Authenticated and decrypted packets
// will be written to the interface immediately (except heartbeat ones).
func (p *Peer) PktProcess(data []byte, tap io.Writer, ready chan struct{}) bool {
	p.size = len(data)
	copy(p.buf, Emptiness)
	copy(p.tag[:], data[p.size-poly1305.TagSize:])
	copy(p.buf[S20BS:], data[NonceSize:p.size-poly1305.TagSize])
	salsa20.XORKeyStream(
		p.buf[:S20BS+p.size-poly1305.TagSize],
		p.buf[:S20BS+p.size-poly1305.TagSize],
		data[:NonceSize],
		p.Key,
	)
	copy(p.keyAuth[:], p.buf[:SSize])
	if !poly1305.Verify(p.tag, data[:p.size-poly1305.TagSize], p.keyAuth) {
		ready <- struct{}{}
		p.FramesUnauth++
		return false
	}

	// Check if received nonce is known to us in either of two buckets.
	// If yes, then this is ignored duplicate.
	// Check from the oldest bucket, as in most cases this will result
	// in constant time check.
	// If Bucket0 is filled, then it becomes Bucket1.
	p.NonceCipher.Decrypt(p.buf, data[:NonceSize])
	ready <- struct{}{}
	p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize])
	if _, p.nonceFound = p.nonceBucket1[p.NonceRecv]; p.nonceFound {
		p.FramesDup++
		return false
	}
	if _, p.nonceFound = p.nonceBucket0[p.NonceRecv]; p.nonceFound {
		p.FramesDup++
		return false
	}
	p.nonceBucket0[p.NonceRecv] = struct{}{}
	p.nonceBucketN++
	if p.nonceBucketN == NonceBucketSize {
		p.nonceBucket1 = p.nonceBucket0
		p.nonceBucket0 = make(map[uint64]struct{}, NonceBucketSize)
		p.nonceBucketN = 0
	}

	p.FramesIn++
	p.BytesIn += int64(p.size)
	p.LastPing = time.Now()
	p.NonceRecv = p.nonceRecv
	p.pktSize, _ = binary.Uvarint(p.buf[S20BS : S20BS+PktSizeSize])
	if p.pktSize == 0 {
		p.HeartbeatRecv++
		return true
	}
	p.frame = p.buf[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSize]
	p.BytesPayloadIn += int64(p.pktSize)
	tap.Write(p.frame)
	return true
}
Beispiel #8
0
func encrypt_data(plain, keys []byte) ([]byte, error) {
	var iv, key []byte
	var block cipher.Block
	var stream cipher.Stream

	iv_offset := TotalIVLen
	res := make([]byte, len(plain)+iv_offset)

	iv = res[iv_offset-SalsaIVLen : iv_offset]
	_, err := rand.Read(iv)
	if err != nil {
		return nil, err
	}
	// For some reason salsa20 API is different
	key_array := new([32]byte)
	copy(key_array[:], keys[cipherKeyLen*2:])
	salsa20.XORKeyStream(res[iv_offset:], plain, iv, key_array)
	iv_offset -= SalsaIVLen

	iv = res[iv_offset-IVLen : iv_offset]
	_, err = rand.Read(iv)
	if err != nil {
		return nil, err
	}
	key = keys[cipherKeyLen : cipherKeyLen*2]
	block, err = twofish.NewCipher(key)
	if err != nil {
		return nil, err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(res[iv_offset:], res[iv_offset:])
	iv_offset -= IVLen

	iv = res[iv_offset-IVLen : iv_offset]
	_, err = rand.Read(iv)
	if err != nil {
		return nil, err
	}
	key = keys[:cipherKeyLen]
	block, err = aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(res[iv_offset:], res[iv_offset:])
	iv_offset -= IVLen

	if iv_offset != 0 {
		panic(fmt.Errorf("something went terribly wrong: iv_offset final value non-zero"))
	}

	return res, nil
}
Beispiel #9
0
func (rng salsaRNG) Read(buf []byte) (n int, err error) {
	for i := range buf {
		buf[i] = 0
	}

	var nonce [8]byte
	var key [32]byte
	binary.LittleEndian.PutUint32(key[:], uint32(rng.seed))
	rng.seed++
	salsa20.XORKeyStream(buf, buf, nonce[:], &key)

	return len(buf), nil
}
Beispiel #10
0
func newNonceCipher(key *[32]byte) *xtea.Cipher {
	nonceKey := make([]byte, 16)
	salsa20.XORKeyStream(
		nonceKey,
		make([]byte, 32),
		make([]byte, xtea.BlockSize),
		key,
	)
	ciph, err := xtea.NewCipher(nonceKey)
	if err != nil {
		panic(err)
	}
	return ciph
}
Beispiel #11
0
// Encode the data, produce AONT package. Data size will be larger than
// the original one for 48 bytes.
func Encode(r *[RSize]byte, in []byte) ([]byte, error) {
	out := make([]byte, len(in)+HSize+RSize)
	copy(out, in)
	h := blake2b.New256()
	h.Write(r[:])
	h.Write(in)
	copy(out[len(in):], h.Sum(nil))
	salsaKey := new([32]byte)
	copy(salsaKey[:], r[:])
	salsa20.XORKeyStream(out, out, dummyNonce, salsaKey)
	h.Reset()
	h.Write(out[:len(in)+32])
	for i, b := range h.Sum(nil)[:RSize] {
		out[len(in)+32+i] = b ^ r[i]
	}
	return out, nil
}
Beispiel #12
0
// Process incoming Ethernet packet.
// ready channel is TAPListen's synchronization channel used to tell him
// that he is free to receive new packets. Encrypted and authenticated
// packets will be sent to remote Peer side immediately.
func (p *Peer) EthProcess(data []byte, ready chan struct{}) {
	p.now = time.Now()
	p.size = len(data)
	// If this heartbeat is necessary
	if p.size == 0 && !p.LastSent.Add(p.Timeout).Before(p.now) {
		return
	}
	copy(p.buf, Emptiness)
	if p.size > 0 {
		copy(p.buf[S20BS+PktSizeSize:], data)
		ready <- struct{}{}
		binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(p.size))
		p.BytesPayloadOut += int64(p.size)
	} else {
		p.HeartbeatSent++
	}

	p.NonceOur += 2
	copy(p.nonce, Emptiness)
	binary.PutUvarint(p.nonce, p.NonceOur)
	p.NonceCipher.Encrypt(p.nonce, p.nonce)

	salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
	copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
	copy(p.keyAuth[:], p.buf[:SSize])
	if p.NoiseEnable {
		p.frame = p.buf[S20BS-NonceSize : S20BS+MTU-NonceSize-poly1305.TagSize]
	} else {
		p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+p.size]
	}
	poly1305.Sum(p.tag, p.frame, p.keyAuth)

	p.BytesOut += int64(len(p.frame) + poly1305.TagSize)
	p.FramesOut++

	if p.CPRCycle != time.Duration(0) {
		p.willSentCycle = p.LastSent.Add(p.CPRCycle)
		if p.willSentCycle.After(p.now) {
			time.Sleep(p.willSentCycle.Sub(p.now))
			p.now = p.willSentCycle
		}
	}
	p.LastSent = p.now
	p.Conn.Write(append(p.frame, p.tag[:]...))
}
Beispiel #13
0
// Decode the data from AONT package. Data size will be smaller than the
// original one for 48 bytes.
func Decode(in []byte) ([]byte, error) {
	if len(in) < HSize+RSize {
		return nil, errors.New("Too small input buffer")
	}
	h := blake2b.New256()
	h.Write(in[:len(in)-RSize])
	salsaKey := new([32]byte)
	for i, b := range h.Sum(nil)[:RSize] {
		salsaKey[i] = b ^ in[len(in)-RSize+i]
	}
	h.Reset()
	h.Write(salsaKey[:RSize])
	out := make([]byte, len(in)-RSize)
	salsa20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, salsaKey)
	h.Write(out[:len(out)-HSize])
	if subtle.ConstantTimeCompare(h.Sum(nil), out[len(out)-HSize:]) != 1 {
		return nil, errors.New("Invalid checksum")
	}
	return out[:len(out)-HSize], nil
}
Beispiel #14
0
func decrypt_data(dst, data, keys []byte) error {
	var iv, key []byte
	var block cipher.Block
	var stream cipher.Stream
	var err error

	buffer := append([]byte{}, data...)

	iv_offset := IVLen
	iv = buffer[:iv_offset]
	key = keys[:cipherKeyLen]
	block, err = aes.NewCipher(key)
	if err != nil {
		return err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(buffer[iv_offset:], buffer[iv_offset:])

	iv_offset += IVLen
	iv = buffer[iv_offset-IVLen : iv_offset]
	key = keys[cipherKeyLen : cipherKeyLen*2]
	block, err = twofish.NewCipher(key)
	if err != nil {
		return err
	}
	stream = cipher.NewCTR(block, iv)
	stream.XORKeyStream(buffer[iv_offset:], buffer[iv_offset:])

	iv_offset += SalsaIVLen
	iv = buffer[iv_offset-SalsaIVLen : iv_offset]
	key_array := new([32]byte)
	copy(key_array[:], keys[cipherKeyLen*2:])
	salsa20.XORKeyStream(dst, buffer[iv_offset:], iv, key_array)

	if len(buffer[iv_offset:]) != len(data)-TotalIVLen {
		return fmt.Errorf("something went terribly wrong: bufsz is wrong")
	}

	return nil
}
Beispiel #15
0
// Process handshake message on the server side.
// This function is intended to be called on server's side.
// If this is the final handshake message, then new Peer object
// will be created and used as a transport. If no mutually
// authenticated Peer is ready, then return nil.
func (h *Handshake) Server(data []byte) *Peer {
	// R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag
	if h.rNonce == nil {
		// Generate DH keypair
		var dhPubRepr *[32]byte
		h.dhPriv, dhPubRepr = dhKeypairGen()

		h.rNonce = new([RSize]byte)
		copy(h.rNonce[:], data[:RSize])

		// Decrypt remote public key and compute shared key
		cDHRepr := new([32]byte)
		salsa20.XORKeyStream(
			cDHRepr[:],
			data[RSize:RSize+32],
			h.rNonce[:],
			h.dsaPubH,
		)
		cDH := new([32]byte)
		extra25519.RepresentativeToPublicKey(cDH, cDHRepr)
		h.key = dhKeyGen(h.dhPriv, cDH)

		encPub := make([]byte, 32)
		salsa20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)

		// Generate R* and encrypt them
		h.rServer = new([RSize]byte)
		if err := randRead(h.rServer[:]); err != nil {
			log.Fatalln("Error reading random for R:", err)
		}
		h.sServer = new([SSize]byte)
		if err := randRead(h.sServer[:]); err != nil {
			log.Fatalln("Error reading random for S:", err)
		}
		var encRs []byte
		if h.Conf.Noise {
			encRs = make([]byte, MTU-len(encPub)-xtea.BlockSize)
		} else {
			encRs = make([]byte, RSize+SSize)
		}
		copy(encRs, append(h.rServer[:], h.sServer[:]...))
		salsa20.XORKeyStream(encRs, encRs, h.rNonce[:], h.key)

		// Send that to client
		h.conn.Write(append(encPub, append(encRs, idTag(h.Conf.Id, encPub)...)...))
		h.LastPing = time.Now()
	} else
	// ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag
	if h.rClient == nil {
		// Decrypted Rs compare rServer
		dec := make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
		salsa20.XORKeyStream(
			dec,
			data[:RSize+RSize+SSize+ed25519.SignatureSize],
			h.rNonceNext(1),
			h.key,
		)
		if subtle.ConstantTimeCompare(dec[:RSize], h.rServer[:]) != 1 {
			log.Println("Invalid server's random number with", h.addr)
			return nil
		}
		sign := new([ed25519.SignatureSize]byte)
		copy(sign[:], dec[RSize+RSize+SSize:])
		if !ed25519.Verify(h.Conf.DSAPub, h.key[:], sign) {
			log.Println("Invalid signature from", h.addr)
			return nil
		}

		// Send final answer to client
		var enc []byte
		if h.Conf.Noise {
			enc = make([]byte, MTU-xtea.BlockSize)
		} else {
			enc = make([]byte, RSize)
		}
		copy(enc, dec[RSize:RSize+RSize])
		salsa20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
		h.conn.Write(append(enc, idTag(h.Conf.Id, enc)...))

		// Switch peer
		peer := newPeer(
			false,
			h.addr,
			h.conn,
			h.Conf,
			keyFromSecrets(h.sServer[:], dec[RSize+RSize:RSize+RSize+SSize]))
		h.LastPing = time.Now()
		return peer
	} else {
		log.Println("Invalid handshake message from", h.addr)
	}
	return nil
}
Beispiel #16
0
func EncryptEvent(buf *bytes.Buffer, ev Event, ctx *CryptoContext) error {
	start := buf.Len()
	buf.Write(make([]byte, 4))
	var header EventHeader
	header.Type = GetRegistType(ev)
	header.Id = ev.GetId()
	header.Flags = 0
	header.Encode(buf)
	method := ctx.Method
	ev.Encode(buf)

	elen := uint32(buf.Len() - start)
	eventContent := buf.Bytes()[start+4:]

	var nonce []byte
	encryptIV := ctx.EncryptIV
	if header.Type == EventAuth {
		method = uint8(Salsa20Encrypter)
		encryptIV = 0
		if elen > 256 {
			log.Fatalf("Too large auth event with length:%d", elen)
		}
	}
	switch method {
	case Salsa20Encrypter:
		fallthrough
	case Chacha20Encrypter:
		nonce = make([]byte, 8)
	case AES256Encrypter:
		nonce = make([]byte, 12)
		elen += uint32(aes256gcm.Overhead())
	}
	if len(nonce) > 0 {
		iv := encryptIV ^ uint64(elen)
		binary.LittleEndian.PutUint64(nonce, iv)
	}

	switch method {
	case Salsa20Encrypter:
		salsa20.XORKeyStream(eventContent, eventContent, nonce, &salsa20Key)
	case RC4Encrypter:
		rc4Cipher, _ := rc4.NewCipher(secretKey)
		rc4Cipher.XORKeyStream(eventContent, eventContent)
	case AES256Encrypter:
		bb := aes256gcm.Seal(eventContent[:0], nonce, eventContent, nil)
		if len(bb)-len(eventContent) != aes256gcm.Overhead() {
			log.Printf("Expected aes bytes %d  after encrypt %d bytes", len(bb), len(eventContent))
		}
		copy(eventContent, bb[0:len(eventContent)])
		if len(bb) > len(eventContent) {
			buf.Write(bb[len(eventContent):])
		}
	case Chacha20Encrypter:
		chacha20XOR(nonce, eventContent, eventContent)
		//chacha20Cipher, _ := chacha20.New(secretKey, nonce)
		//chacha20Cipher.XORKeyStream(eventContent, eventContent)
	}

	//log.Printf("Enc event(%d):%T with iv:%d with len:%d_%d %d", ev.GetId(), ev, encryptIV, elen, len(eventContent), method)
	if header.Type == EventAuth {
		base := rand.Int31n(0xFFFFFF)
		elen = (uint32(base) << 8) + elen
	} else {
		elen = elen ^ uint32(encryptIV)
	}
	binary.LittleEndian.PutUint32(buf.Bytes()[start:start+4], elen)
	if header.Type != EventAuth {
		ctx.EncryptIV++
	}
	return nil
}
Beispiel #17
0
func DecryptEvent(buf *bytes.Buffer, ctx *CryptoContext) (err error, ev Event) {
	if buf.Len() < 4 {
		return EBNR, nil
	}
	elen := binary.LittleEndian.Uint32(buf.Bytes()[0:4])
	method := ctx.Method
	if method == 0 && ctx.DecryptIV == 0 {
		method = Salsa20Encrypter
		elen = elen & uint32(0xFF)
	} else {
		elen = elen ^ uint32(ctx.DecryptIV)
	}
	if elen > uint32(buf.Len()) {
		return EBNR, nil
	}
	if elen >= largeEventLimit {
		return ErrToolargeEvent, nil
	}
	buf.Next(4)
	body := buf.Next(int(elen - 4))

	var nonce []byte
	switch method {
	case Salsa20Encrypter:
		fallthrough
	case Chacha20Encrypter:
		nonce = make([]byte, 8)
	case AES256Encrypter:
		nonce = make([]byte, 12)
	}
	if len(nonce) > 0 {
		iv := ctx.DecryptIV ^ uint64(elen)
		binary.LittleEndian.PutUint64(nonce, iv)
	}

	switch method {
	case Salsa20Encrypter:
		salsa20.XORKeyStream(body, body, nonce, &salsa20Key)
	case RC4Encrypter:
		rc4Cipher, _ := rc4.NewCipher(secretKey)
		rc4Cipher.XORKeyStream(body, body)
	case AES256Encrypter:
		bb, err := aes256gcm.Open(body[:0], nonce, body, nil)
		if nil != err {
			return err, nil
		}
		body = bb
	case Chacha20Encrypter:
		chacha20XOR(nonce, body, body)
		//cipher, _ := chacha20.New(secretKey, nonce)
		//cipher.XORKeyStream(body, body)
	}
	ebuf := bytes.NewBuffer(body)
	var header EventHeader
	if err = header.Decode(ebuf); nil != err {
		log.Printf("Failed to decode event header")
		return
	}
	//log.Printf("Dec event(%d) with iv:%d with len:%d_%d  %d  %d", header.Id, ctx.DecryptIV, elen, len(body), method, header.Type)
	var tmp interface{}
	if err, tmp = NewEventInstance(header.Type); nil != err {
		log.Printf("Failed to decode event with err:%v with len:%d", err, elen)
		return
	}
	ev = tmp.(Event)
	ev.SetId(header.Id)
	err = ev.Decode(ebuf)
	if nil != err {
		log.Printf("Failed to decode event:%T with err:%v with len:%d", tmp, err, elen)
	}
	if header.Type != EventAuth {
		ctx.DecryptIV++
	}
	return
}
Beispiel #18
0
func (session *CryptoSession) Decrypt(ciphertext []byte) string {
	out := make([]byte, len(ciphertext))
	salsa20.XORKeyStream(out, ciphertext, Session.nonce, Session.sessionKey)
	return string(out)
}
Beispiel #19
0
// Process handshake message on the client side.
// This function is intended to be called on client's side.
// If this is the final handshake message, then new Peer object
// will be created and used as a transport. If no mutually
// authenticated Peer is ready, then return nil.
func (h *Handshake) Client(data []byte) *Peer {
	// ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag
	if h.rServer == nil && h.key == nil {
		// Decrypt remote public key and compute shared key
		sDHRepr := new([32]byte)
		salsa20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH)
		sDH := new([32]byte)
		extra25519.RepresentativeToPublicKey(sDH, sDHRepr)
		h.key = dhKeyGen(h.dhPriv, sDH)

		// Decrypt Rs
		decRs := make([]byte, RSize+SSize)
		salsa20.XORKeyStream(decRs, data[SSize:32+RSize+SSize], h.rNonce[:], h.key)
		h.rServer = new([RSize]byte)
		copy(h.rServer[:], decRs[:RSize])
		h.sServer = new([SSize]byte)
		copy(h.sServer[:], decRs[RSize:])

		// Generate R* and signature and encrypt them
		h.rClient = new([RSize]byte)
		if err := randRead(h.rClient[:]); err != nil {
			log.Fatalln("Error reading random for R:", err)
		}
		h.sClient = new([SSize]byte)
		if err := randRead(h.sClient[:]); err != nil {
			log.Fatalln("Error reading random for S:", err)
		}
		sign := ed25519.Sign(h.Conf.DSAPriv, h.key[:])

		var enc []byte
		if h.Conf.Noise {
			enc = make([]byte, MTU-xtea.BlockSize)
		} else {
			enc = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
		}
		copy(enc,
			append(h.rServer[:],
				append(h.rClient[:],
					append(h.sClient[:], sign[:]...)...)...))
		salsa20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)

		// Send that to server
		h.conn.Write(append(enc, idTag(h.Conf.Id, enc)...))
		h.LastPing = time.Now()
	} else
	// ENC(K, R+2, RC) + IDtag
	if h.key != nil {
		// Decrypt rClient
		dec := make([]byte, RSize)
		salsa20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
		if subtle.ConstantTimeCompare(dec, h.rClient[:]) != 1 {
			log.Println("Invalid client's random number with", h.addr)
			return nil
		}

		// Switch peer
		peer := newPeer(
			true,
			h.addr,
			h.conn,
			h.Conf,
			keyFromSecrets(h.sServer[:], h.sClient[:]),
		)
		h.LastPing = time.Now()
		return peer
	} else {
		log.Println("Invalid handshake stage from", h.addr)
	}
	return nil
}
Beispiel #20
0
// Process handshake message on the client side.
// This function is intended to be called on client's side.
// If this is the final handshake message, then new Peer object
// will be created and used as a transport. If no mutually
// authenticated Peer is ready, then return nil.
func (h *Handshake) Client(data []byte) *Peer {
	// ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag
	if h.rServer == nil && h.key == nil &&
		((!h.Conf.Encless && len(data) >= 80) ||
			(h.Conf.Encless && len(data) == 2*(EnclessEnlargeSize+h.Conf.MTU))) {
		// Decrypt remote public key
		sDHRepr := new([32]byte)
		var tmp []byte
		var err error
		if h.Conf.Encless {
			tmp, err = EnclessDecode(
				h.dsaPubH,
				h.rNonceNext(1),
				data[:len(data)/2],
			)
			if err != nil {
				log.Println("Unable to decode packet from", h.addr, err)
				return nil
			}
			copy(sDHRepr[:], tmp[:32])
		} else {
			salsa20.XORKeyStream(
				sDHRepr[:],
				data[:32],
				h.rNonceNext(1),
				h.dsaPubH,
			)
		}

		// Compute shared key
		sDH := new([32]byte)
		extra25519.RepresentativeToPublicKey(sDH, sDHRepr)
		h.key = dhKeyGen(h.dhPriv, sDH)

		// Decrypt Rs
		h.rServer = new([RSize]byte)
		h.sServer = new([SSize]byte)
		if h.Conf.Encless {
			tmp, err = EnclessDecode(
				h.key,
				h.rNonce[:],
				data[len(data)/2:len(data)-xtea.BlockSize],
			)
			if err != nil {
				log.Println("Unable to decode packet from", h.addr, err)
				return nil
			}
			copy(h.rServer[:], tmp[:RSize])
			copy(h.sServer[:], tmp[RSize:RSize+SSize])
		} else {
			decRs := make([]byte, RSize+SSize)
			salsa20.XORKeyStream(
				decRs,
				data[SSize:SSize+RSize+SSize],
				h.rNonce[:],
				h.key,
			)
			copy(h.rServer[:], decRs[:RSize])
			copy(h.sServer[:], decRs[RSize:])
		}

		// Generate R* and signature and encrypt them
		h.rClient = new([RSize]byte)
		if _, err = Rand.Read(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 {
			log.Fatalln("Error reading random for S:", err)
		}
		sign := ed25519.Sign(h.Conf.DSAPriv, h.key[:])

		var enc []byte
		if h.Conf.Noise {
			enc = make([]byte, h.Conf.MTU-xtea.BlockSize)
		} else {
			enc = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
		}
		copy(enc, h.rServer[:])
		copy(enc[RSize:], h.rClient[:])
		copy(enc[RSize+RSize:], h.sClient[:])
		copy(enc[RSize+RSize+SSize:], sign[:])
		if h.Conf.Encless {
			enc, err = EnclessEncode(h.key, h.rNonceNext(1), enc)
			if err != nil {
				panic(err)
			}
		} else {
			salsa20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)
		}

		// Send that to server
		h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
		h.LastPing = time.Now()
	} else
	// ENC(K, R+2, RC) + IDtag
	if h.key != nil && ((!h.Conf.Encless && len(data) >= 16) ||
		(h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
		var err error
		// Decrypt rClient
		var dec []byte
		if h.Conf.Encless {
			dec, err = EnclessDecode(
				h.key,
				h.rNonceNext(2),
				data[:len(data)-xtea.BlockSize],
			)
			if err != nil {
				log.Println("Unable to decode packet from", h.addr, err)
				return nil
			}
			dec = dec[:RSize]
		} else {
			dec = make([]byte, RSize)
			salsa20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
		}
		if subtle.ConstantTimeCompare(dec, h.rClient[:]) != 1 {
			log.Println("Invalid client's random number with", h.addr)
			return nil
		}

		// Switch peer
		peer := newPeer(
			true,
			h.addr,
			h.conn,
			h.Conf,
			keyFromSecrets(h.sServer[:], h.sClient[:]),
		)
		h.LastPing = time.Now()
		return peer
	} else {
		log.Println("Invalid handshake stage from", h.addr)
	}
	return nil
}
Beispiel #21
0
// Process handshake message on the server side.
// This function is intended to be called on server's side.
// If this is the final handshake message, then new Peer object
// will be created and used as a transport. If no mutually
// authenticated Peer is ready, then return nil.
func (h *Handshake) Server(data []byte) *Peer {
	// R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag
	if h.rNonce == nil && ((!h.Conf.Encless && len(data) >= 48) ||
		(h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
		h.rNonce = new([RSize]byte)
		copy(h.rNonce[:], data[:RSize])

		// Decrypt remote public key
		cDHRepr := new([32]byte)
		if h.Conf.Encless {
			out, err := EnclessDecode(
				h.dsaPubH,
				h.rNonce[:],
				data[RSize:len(data)-xtea.BlockSize],
			)
			if err != nil {
				log.Println("Unable to decode packet from", h.addr, err)
				return nil
			}
			copy(cDHRepr[:], out)
		} else {
			salsa20.XORKeyStream(
				cDHRepr[:],
				data[RSize:RSize+32],
				h.rNonce[:],
				h.dsaPubH,
			)
		}

		// Generate DH keypair
		var dhPubRepr *[32]byte
		h.dhPriv, dhPubRepr = dhKeypairGen()

		// Compute shared key
		cDH := new([32]byte)
		extra25519.RepresentativeToPublicKey(cDH, cDHRepr)
		h.key = dhKeyGen(h.dhPriv, cDH)

		var encPub []byte
		var err error
		if h.Conf.Encless {
			encPub = make([]byte, h.Conf.MTU)
			copy(encPub, dhPubRepr[:])
			encPub, err = EnclessEncode(h.dsaPubH, h.rNonceNext(1), encPub)
			if err != nil {
				panic(err)
			}
		} else {
			encPub = make([]byte, 32)
			salsa20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)
		}

		// Generate R* and encrypt them
		h.rServer = new([RSize]byte)
		if _, err = Rand.Read(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 {
			log.Fatalln("Error reading random for S:", err)
		}
		var encRs []byte
		if h.Conf.Noise && !h.Conf.Encless {
			encRs = make([]byte, h.Conf.MTU-len(encPub)-xtea.BlockSize)
		} else if h.Conf.Encless {
			encRs = make([]byte, h.Conf.MTU-xtea.BlockSize)
		} else {
			encRs = make([]byte, RSize+SSize)
		}
		copy(encRs, append(h.rServer[:], h.sServer[:]...))
		if h.Conf.Encless {
			encRs, err = EnclessEncode(h.key, h.rNonce[:], encRs)
			if err != nil {
				panic(err)
			}
		} else {
			salsa20.XORKeyStream(encRs, encRs, h.rNonce[:], h.key)
		}

		// Send that to client
		h.conn.Write(append(encPub, append(
			encRs, idTag(h.Conf.Id, h.Conf.TimeSync, encPub)...,
		)...))
		h.LastPing = time.Now()
	} else
	// ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag
	if h.rClient == nil && ((!h.Conf.Encless && len(data) >= 120) ||
		(h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
		var dec []byte
		var err error
		if h.Conf.Encless {
			dec, err = EnclessDecode(
				h.key,
				h.rNonceNext(1),
				data[:len(data)-xtea.BlockSize],
			)
			if err != nil {
				log.Println("Unable to decode packet from", h.addr, err)
				return nil
			}
			dec = dec[:RSize+RSize+SSize+ed25519.SignatureSize]
		} else {
			dec = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
			salsa20.XORKeyStream(
				dec,
				data[:RSize+RSize+SSize+ed25519.SignatureSize],
				h.rNonceNext(1),
				h.key,
			)
		}
		if subtle.ConstantTimeCompare(dec[:RSize], h.rServer[:]) != 1 {
			log.Println("Invalid server's random number with", h.addr)
			return nil
		}
		sign := new([ed25519.SignatureSize]byte)
		copy(sign[:], dec[RSize+RSize+SSize:])
		if !ed25519.Verify(h.Conf.Verifier.Pub, h.key[:], sign) {
			log.Println("Invalid signature from", h.addr)
			return nil
		}

		// Send final answer to client
		var enc []byte
		if h.Conf.Noise {
			enc = make([]byte, h.Conf.MTU-xtea.BlockSize)
		} else {
			enc = make([]byte, RSize)
		}
		copy(enc, dec[RSize:RSize+RSize])
		if h.Conf.Encless {
			enc, err = EnclessEncode(h.key, h.rNonceNext(2), enc)
			if err != nil {
				panic(err)
			}
		} else {
			salsa20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
		}
		h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))

		// Switch peer
		peer := newPeer(
			false,
			h.addr,
			h.conn,
			h.Conf,
			keyFromSecrets(h.sServer[:], dec[RSize+RSize:RSize+RSize+SSize]))
		h.LastPing = time.Now()
		return peer
	} else {
		log.Println("Invalid handshake message from", h.addr)
	}
	return nil
}
Beispiel #22
0
// Process incoming Ethernet packet.
// ready channel is TAPListen's synchronization channel used to tell him
// that he is free to receive new packets. Encrypted and authenticated
// packets will be sent to remote Peer side immediately.
func (p *Peer) EthProcess(data []byte) {
	p.now = time.Now()
	p.BusyT.Lock()

	// Zero size is a heartbeat packet
	if len(data) == 0 {
		// If this heartbeat is necessary
		if !p.LastSent.Add(p.Timeout).Before(p.now) {
			p.BusyT.Unlock()
			return
		}
		p.bufT[S20BS+0] = byte(0)
		p.bufT[S20BS+1] = byte(0)
		p.HeartbeatSent++
	} else {
		// Copy payload to our internal buffer and we are ready to
		// accept the next one
		binary.BigEndian.PutUint16(
			p.bufT[S20BS:S20BS+PktSizeSize],
			uint16(len(data)),
		)
		copy(p.bufT[S20BS+PktSizeSize:], data)
		p.BytesPayloadOut += int64(len(data))
	}

	if p.NoiseEnable {
		p.frameT = p.bufT[S20BS : S20BS+MTU-TagSize]
	} else {
		p.frameT = p.bufT[S20BS : S20BS+PktSizeSize+len(data)+NonceSize]
	}
	p.nonceOur += 2
	binary.BigEndian.PutUint64(p.frameT[len(p.frameT)-NonceSize:], p.nonceOur)
	p.NonceCipher.Encrypt(
		p.frameT[len(p.frameT)-NonceSize:],
		p.frameT[len(p.frameT)-NonceSize:],
	)
	for i := 0; i < SSize; i++ {
		p.bufT[i] = byte(0)
	}
	salsa20.XORKeyStream(
		p.bufT[:S20BS+len(p.frameT)-NonceSize],
		p.bufT[:S20BS+len(p.frameT)-NonceSize],
		p.frameT[len(p.frameT)-NonceSize:],
		p.Key,
	)

	copy(p.keyAuthT[:], p.bufT[:SSize])
	poly1305.Sum(p.tagT, p.frameT, p.keyAuthT)

	atomic.AddInt64(&p.BytesOut, int64(len(p.frameT)+TagSize))
	p.FramesOut++

	if p.CPRCycle != time.Duration(0) {
		p.willSentCycle = p.LastSent.Add(p.CPRCycle)
		if p.willSentCycle.After(p.now) {
			time.Sleep(p.willSentCycle.Sub(p.now))
			p.now = p.willSentCycle
		}
	}

	p.LastSent = p.now
	p.Conn.Write(append(p.tagT[:], p.frameT...))
	p.BusyT.Unlock()
}
Beispiel #23
0
// Pack locks a given payload using the golang.org/x/crypto/salsa20 implementation
func (m SalsaManager) Pack(payload []byte) string {
	out := make([]byte, len(payload))
	salsa20.XORKeyStream(out, payload, iv, &m.key)
	return base64.StdEncoding.EncodeToString(out)
}
Beispiel #24
0
func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
	if len(data) < MinPktLength {
		return false
	}
	p.BusyR.Lock()
	for i := 0; i < SSize; i++ {
		p.bufR[i] = byte(0)
	}
	copy(p.bufR[S20BS:], data[TagSize:])
	salsa20.XORKeyStream(
		p.bufR[:S20BS+len(data)-TagSize-NonceSize],
		p.bufR[:S20BS+len(data)-TagSize-NonceSize],
		data[len(data)-NonceSize:],
		p.Key,
	)

	copy(p.keyAuthR[:], p.bufR[:SSize])
	copy(p.tagR[:], data[:TagSize])
	if !poly1305.Verify(p.tagR, data[TagSize:], p.keyAuthR) {
		p.FramesUnauth++
		p.BusyR.Unlock()
		return false
	}

	// Check if received nonce is known to us in either of two buckets.
	// If yes, then this is ignored duplicate.
	// Check from the oldest bucket, as in most cases this will result
	// in constant time check.
	// If Bucket0 is filled, then it becomes Bucket1.
	p.NonceCipher.Decrypt(
		data[len(data)-NonceSize:],
		data[len(data)-NonceSize:],
	)
	p.nonceRecv = binary.BigEndian.Uint64(data[len(data)-NonceSize:])
	if reorderable {
		_, p.nonceFound0 = p.nonceBucket0[p.nonceRecv]
		_, p.nonceFound1 = p.nonceBucket1[p.nonceRecv]
		if p.nonceFound0 || p.nonceFound1 || p.nonceRecv+2*NonceBucketSize < p.nonceLatest {
			p.FramesDup++
			p.BusyR.Unlock()
			return false
		}
		p.nonceBucket0[p.nonceRecv] = struct{}{}
		p.nonceBucketN++
		if p.nonceBucketN == NonceBucketSize {
			p.nonceBucket1 = p.nonceBucket0
			p.nonceBucket0 = make(map[uint64]struct{}, NonceBucketSize)
			p.nonceBucketN = 0
		}
	} else {
		if p.nonceRecv != p.NonceExpect {
			p.FramesDup++
			p.BusyR.Unlock()
			return false
		}
		p.NonceExpect += 2
	}
	if p.nonceRecv > p.nonceLatest {
		p.nonceLatest = p.nonceRecv
	}

	p.FramesIn++
	atomic.AddInt64(&p.BytesIn, int64(len(data)))
	p.LastPing = time.Now()
	p.pktSizeR = binary.BigEndian.Uint16(p.bufR[S20BS : S20BS+PktSizeSize])

	if p.pktSizeR == 0 {
		p.HeartbeatRecv++
		p.BusyR.Unlock()
		return true
	}
	if int(p.pktSizeR) > len(data)-MinPktLength {
		return false
	}
	p.BytesPayloadIn += int64(p.pktSizeR)
	tap.Write(p.bufR[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSizeR])
	p.BusyR.Unlock()
	return true
}
Beispiel #25
0
// Unpack unlocks a given payload using the golang.org/x/crypto/salsa20 implementation
func (m SalsaManager) Unpack(payload string) []byte {
	in, _ := base64.StdEncoding.DecodeString(payload)
	out := make([]byte, len(in))
	salsa20.XORKeyStream(out, in, iv, &m.key)
	return out
}
Beispiel #26
0
// Process incoming Ethernet packet.
// ready channel is TAPListen's synchronization channel used to tell him
// that he is free to receive new packets. Encrypted and authenticated
// packets will be sent to remote Peer side immediately.
func (p *Peer) EthProcess(data []byte) {
	if len(data) > p.MTU-1 { // 1 is for padding byte
		log.Println("Padded data packet size", len(data)+1, "is bigger than MTU", p.MTU, p)
		return
	}
	p.now = time.Now()
	p.BusyT.Lock()

	// Zero size is a heartbeat packet
	SliceZero(p.bufT)
	if len(data) == 0 {
		// If this heartbeat is necessary
		if !p.LastSent.Add(p.Timeout).Before(p.now) {
			p.BusyT.Unlock()
			return
		}
		p.bufT[S20BS+0] = PadByte
		p.HeartbeatSent++
	} else {
		// Copy payload to our internal buffer and we are ready to
		// accept the next one
		copy(p.bufT[S20BS:], data)
		p.bufT[S20BS+len(data)] = PadByte
		p.BytesPayloadOut += uint64(len(data))
	}

	if p.NoiseEnable && !p.Encless {
		p.frameT = p.bufT[S20BS : S20BS+p.MTU-TagSize]
	} else if p.Encless {
		p.frameT = p.bufT[S20BS : S20BS+p.MTU]
	} else {
		p.frameT = p.bufT[S20BS : S20BS+len(data)+1+NonceSize]
	}
	p.nonceOur += 2
	binary.BigEndian.PutUint64(p.frameT[len(p.frameT)-NonceSize:], p.nonceOur)
	p.NonceCipher.Encrypt(
		p.frameT[len(p.frameT)-NonceSize:],
		p.frameT[len(p.frameT)-NonceSize:],
	)
	var out []byte
	if p.Encless {
		var err error
		out, err = EnclessEncode(
			p.Key,
			p.frameT[len(p.frameT)-NonceSize:],
			p.frameT[:len(p.frameT)-NonceSize],
		)
		if err != nil {
			panic(err)
		}
		out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
	} else {
		salsa20.XORKeyStream(
			p.bufT[:S20BS+len(p.frameT)-NonceSize],
			p.bufT[:S20BS+len(p.frameT)-NonceSize],
			p.frameT[len(p.frameT)-NonceSize:],
			p.Key,
		)
		copy(p.keyAuthT[:], p.bufT[:SSize])
		poly1305.Sum(p.tagT, p.frameT, p.keyAuthT)
		atomic.AddUint64(&p.BytesOut, uint64(len(p.frameT)+TagSize))
		out = append(p.tagT[:], p.frameT...)
	}
	p.FramesOut++

	if p.CPRCycle != time.Duration(0) {
		p.willSentCycle = p.LastSent.Add(p.CPRCycle)
		if p.willSentCycle.After(p.now) {
			time.Sleep(p.willSentCycle.Sub(p.now))
			p.now = p.willSentCycle
		}
	}

	p.LastSent = p.now
	p.Conn.Write(out)
	p.BusyT.Unlock()
}