Beispiel #1
0
// NewDecoder creates a new Decoder instance.  It must be supplied a slice
// containing exactly KeyLength bytes of keying material.
func NewDecoder(key []byte) *Decoder {
	if len(key) != KeyLength {
		panic(fmt.Sprintf("BUG: Invalid decoder key length: %d", len(key)))
	}

	decoder := new(Decoder)
	copy(decoder.key[:], key[0:keyLength])
	decoder.nonce.init(key[keyLength : keyLength+noncePrefixLength])
	seed, err := drbg.SeedFromBytes(key[keyLength+noncePrefixLength:])
	if err != nil {
		panic(fmt.Sprintf("BUG: Failed to initialize DRBG: %s", err))
	}
	decoder.drbg, _ = drbg.NewHashDrbg(seed)

	return decoder
}
Beispiel #2
0
func newObfs4ClientConn(conn net.Conn, args *obfs4ClientArgs) (c *obfs4Conn, err error) {
	// Generate the initial protocol polymorphism distribution(s).
	var seed *drbg.Seed
	if seed, err = drbg.NewSeed(); err != nil {
		return
	}
	lenDist := probdist.New(seed, 0, framing.MaximumSegmentLength, biasedDist)
	var iatDist *probdist.WeightedDist
	if args.iatMode != iatNone {
		var iatSeed *drbg.Seed
		iatSeedSrc := sha256.Sum256(seed.Bytes()[:])
		if iatSeed, err = drbg.SeedFromBytes(iatSeedSrc[:]); err != nil {
			return
		}
		iatDist = probdist.New(iatSeed, 0, maxIATDelay, biasedDist)
	}

	// Allocate the client structure.
	c = &obfs4Conn{conn, false, lenDist, iatDist, args.iatMode, bytes.NewBuffer(nil), bytes.NewBuffer(nil), nil, nil}

	// Start the handshake timeout.
	deadline := time.Now().Add(clientHandshakeTimeout)
	if err = conn.SetDeadline(deadline); err != nil {
		return nil, err
	}

	if err = c.clientHandshake(args.nodeID, args.publicKey, args.sessionKey); err != nil {
		return nil, err
	}

	// Stop the handshake timeout.
	if err = conn.SetDeadline(time.Time{}); err != nil {
		return nil, err
	}

	return
}
Beispiel #3
0
// ServerFactory returns a new obfs4ServerFactory instance.
func (t *Transport) ServerFactory(stateDir string, args *pt.Args) (base.ServerFactory, error) {
	st, err := serverStateFromArgs(stateDir, args)
	if err != nil {
		return nil, err
	}

	var iatSeed *drbg.Seed
	if st.iatMode != iatNone {
		iatSeedSrc := sha256.Sum256(st.drbgSeed.Bytes()[:])
		var err error
		iatSeed, err = drbg.SeedFromBytes(iatSeedSrc[:])
		if err != nil {
			return nil, err
		}
	}

	// Store the arguments that should appear in our descriptor for the clients.
	ptArgs := pt.Args{}
	ptArgs.Add(certArg, st.cert.String())
	ptArgs.Add(iatArg, strconv.Itoa(st.iatMode))

	// Initialize the replay filter.
	filter, err := replayfilter.New(replayTTL)
	if err != nil {
		return nil, err
	}

	// Initialize the close thresholds for failed connections.
	drbg, err := drbg.NewHashDrbg(st.drbgSeed)
	if err != nil {
		return nil, err
	}
	rng := rand.New(drbg)

	sf := &obfs4ServerFactory{t, &ptArgs, st.nodeID, st.identityKey, st.drbgSeed, iatSeed, st.iatMode, filter, rng.Intn(maxCloseDelayBytes), rng.Intn(maxCloseDelay)}
	return sf, nil
}
Beispiel #4
0
func (conn *obfs4Conn) readPackets() (err error) {
	// Attempt to read off the network.
	var buf [consumeReadSize]byte
	rdLen, rdErr := conn.Conn.Read(buf[:])
	conn.receiveBuffer.Write(buf[:rdLen])

	var decoded [framing.MaximumFramePayloadLength]byte
	for conn.receiveBuffer.Len() > 0 {
		// Decrypt an AEAD frame.
		decLen := 0
		decLen, err = conn.decoder.Decode(decoded[:], conn.receiveBuffer)
		if err == framing.ErrAgain {
			break
		} else if err != nil {
			break
		} else if decLen < packetOverhead {
			err = InvalidPacketLengthError(decLen)
			break
		}

		// Decode the packet.
		pkt := decoded[0:decLen]
		pktType := pkt[0]
		payloadLen := binary.BigEndian.Uint16(pkt[1:])
		if int(payloadLen) > len(pkt)-packetOverhead {
			err = InvalidPayloadLengthError(int(payloadLen))
			break
		}
		payload := pkt[3 : 3+payloadLen]

		switch pktType {
		case packetTypePayload:
			if payloadLen > 0 {
				conn.receiveDecodedBuffer.Write(payload)
			}
		case packetTypePrngSeed:
			// Only regenerate the distribution if we are the client.
			if len(payload) == seedPacketPayloadLength && !conn.isServer {
				var seed *drbg.Seed
				seed, err = drbg.SeedFromBytes(payload)
				if err != nil {
					break
				}
				conn.lenDist.Reset(seed)
				if conn.iatDist != nil {
					iatSeedSrc := sha256.Sum256(seed.Bytes()[:])
					iatSeed, err := drbg.SeedFromBytes(iatSeedSrc[:])
					if err != nil {
						break
					}
					conn.iatDist.Reset(iatSeed)
				}
			}
		default:
			// Ignore unknown packet types.
		}
	}

	// Read errors (all fatal) take priority over various frame processing
	// errors.
	if rdErr != nil {
		return rdErr
	}

	return
}
Beispiel #5
0
func (conn *ssConn) readPackets() error {
	// Consume and buffer up to 1 MSS worth of data.
	var buf [maxSegmentLength]byte
	rdLen, rdErr := conn.Conn.Read(buf[:])
	conn.receiveBuffer.Write(buf[:rdLen])

	// Process incoming packets incrementally.  conn.receiveState stores
	// the results of partial processing.
	for conn.receiveBuffer.Len() > 0 {
		if conn.receiveState.mac == nil {
			// Read and store the packet MAC.
			if conn.receiveBuffer.Len() < macLength {
				break
			}
			mac := make([]byte, macLength)
			conn.receiveBuffer.Read(mac)
			conn.receiveState.mac = mac
		}

		if conn.receiveState.hdr == nil {
			// Read and store the packet header.
			if conn.receiveBuffer.Len() < pktHdrLength {
				break
			}
			hdr := make([]byte, pktHdrLength)
			conn.receiveBuffer.Read(hdr)

			// Add the encrypted packet header to the HMAC instance, and then
			// decrypt it so that the length of the packet can be determined.
			conn.rxCrypto.mac.Reset()
			conn.rxCrypto.mac.Write(hdr)
			conn.rxCrypto.s.XORKeyStream(hdr, hdr)

			// Store the plaintext packet header, and host byte order length
			// values.
			totalLen := int(binary.BigEndian.Uint16(hdr[0:]))
			payloadLen := int(binary.BigEndian.Uint16(hdr[2:]))
			if payloadLen > totalLen || totalLen > maxPayloadLength {
				return ErrInvalidPacket
			}
			conn.receiveState.hdr = hdr
			conn.receiveState.totalLen = totalLen
			conn.receiveState.payloadLen = payloadLen
		}

		var data []byte
		if conn.receiveState.totalLen > 0 {
			// If the packet actually has payload (including padding), read,
			// digest and decrypt it.
			if conn.receiveBuffer.Len() < conn.receiveState.totalLen {
				break
			}
			data = make([]byte, conn.receiveState.totalLen)
			conn.receiveBuffer.Read(data)
			conn.rxCrypto.mac.Write(data)
			conn.rxCrypto.s.XORKeyStream(data, data)
		}

		// Authenticate the packet, by comparing the received MAC with the one
		// calculated over the ciphertext consumed off the network.
		cmpMAC := conn.rxCrypto.mac.Sum(nil)[:macLength]
		if !hmac.Equal(cmpMAC, conn.receiveState.mac[:]) {
			return ErrInvalidPacket
		}

		// Based on the packet flags, do something useful with the payload.
		data = data[:conn.receiveState.payloadLen]
		switch conn.receiveState.hdr[4] {
		case pktPayload:
			// User data, write it into the decoded payload buffer so that Read
			// calls can be serviced.
			conn.receiveDecodedBuffer.Write(data)
		case pktNewTicket:
			// New Session Ticket to be used for future handshakes, store it in
			// the Session Ticket store.
			if conn.isServer || len(data) != ticketKeyLength+ticketLength {
				return ErrInvalidPacket
			}
			conn.ticketStore.storeTicket(conn.RemoteAddr(), data)
		case pktPrngSeed:
			// New PRNG_SEED for the protocol polymorphism.  Regenerate the
			// length obfuscation probability distribution.
			if conn.isServer || len(data) != pktPrngSeedLength {
				return ErrInvalidPacket
			}
			seed, err := drbg.SeedFromBytes(data)
			if err != nil {
				return ErrInvalidPacket
			}
			conn.lenDist.Reset(seed)
		default:
			return ErrInvalidPacket
		}

		// Done processing a packet, clear the partial state.
		conn.receiveState.mac = nil
		conn.receiveState.hdr = nil
		conn.receiveState.totalLen = 0
		conn.receiveState.payloadLen = 0
	}
	return rdErr
}