Browse Source

Replace time factor with timestamp

- The time factor had the same design flaw fixed here for TLS passthrough:
  https://github.com/Psiphon-Labs/psiphon-tunnel-core/commit/f7b2e19338dbe8abf4c1513cc74e5c9205cc5c6d

- Unlike TLS passthrough, we don't need to fit the entire message into a short
  ClientHello field, so we can add a timestamp field. As a result,
  obfuscation keys need only be derived once per session, and, unlike in the
  TLS passthrough fix, we don't need to check multiple possible keys.
Rod Hynes 2 years ago
parent
commit
4d957d91e2

+ 64 - 60
psiphon/common/inproxy/obfuscation.go

@@ -37,7 +37,7 @@ import (
 
 const (
 	obfuscationSessionPacketNonceSize = 12
-	obfuscationAntiReplayTimePeriod   = 20 * time.Minute
+	obfuscationAntiReplayTimePeriod   = 10 * time.Minute
 	obfuscationAntiReplayHistorySize  = 10000000
 )
 
@@ -64,43 +64,19 @@ var antiReplayTimeFactorPeriodSeconds = int64(
 	obfuscationAntiReplayTimePeriod / time.Second)
 
 // deriveObfuscationSecret derives an obfuscation secret from the root secret,
-// a context, and an optional time factor.
-//
-// With a time factor, derived secrets remain valid only for a limited time
-// period. Both ends of an obfuscated communication will derive the same
-// secret based on a shared root secret, a common context, and local clocks.
-// The current time is rounded, allowing the one end's clock to be slightly
-// ahead of or behind of the other end's clock.
-//
-// The time factor can be used in concert with a replay history, bounding the
-// number of historical messages that need to be retained in the history.
+// and context.
 func deriveObfuscationSecret(
 	rootObfuscationSecret ObfuscationSecret,
-	useTimeFactor bool,
 	context string) (ObfuscationSecret, error) {
 
-	var salt []byte
-
-	if useTimeFactor {
-
-		roundedTimePeriod := (time.Now().Unix() +
-			(antiReplayTimeFactorPeriodSeconds / 2)) / antiReplayTimeFactorPeriodSeconds
-
-		var timeFactor [8]byte
-		binary.BigEndian.PutUint64(timeFactor[:], uint64(roundedTimePeriod))
-		salt = timeFactor[:]
-	}
-
 	var key ObfuscationSecret
-
 	_, err := io.ReadFull(
-		hkdf.New(sha256.New, rootObfuscationSecret[:], salt, []byte(context)), key[:])
+		hkdf.New(sha256.New, rootObfuscationSecret[:], nil, []byte(context)), key[:])
 	if err != nil {
 		return key, errors.Trace(err)
 	}
 
 	return key, nil
-
 }
 
 // deriveSessionPacketObfuscationSecret derives a common session obfuscation
@@ -124,16 +100,35 @@ func deriveSessionPacketObfuscationSecret(
 		context = "in-proxy-session-packet-responder-to-initiator"
 	}
 
-	// The time factor is set for upstream; the responder uses an anti-replay
-	// history for packets received from initiators.
-	key, err := deriveObfuscationSecret(rootObfuscationSecret, isUpstream, context)
+	key, err := deriveObfuscationSecret(rootObfuscationSecret, context)
 	if err != nil {
-		return key, errors.Trace(err)
+		return ObfuscationSecret{}, errors.Trace(err)
 	}
 
 	return key, nil
 }
 
+// deriveSessionPacketObfuscationSecrets derives both send and receive
+// obfuscation secrets.
+func deriveSessionPacketObfuscationSecrets(
+	rootObfuscationSecret ObfuscationSecret,
+	isInitiator bool) (ObfuscationSecret, ObfuscationSecret, error) {
+
+	send, err := deriveSessionPacketObfuscationSecret(
+		rootObfuscationSecret, isInitiator, true)
+	if err != nil {
+		return ObfuscationSecret{}, ObfuscationSecret{}, errors.Trace(err)
+	}
+
+	receive, err := deriveSessionPacketObfuscationSecret(
+		rootObfuscationSecret, isInitiator, false)
+	if err != nil {
+		return ObfuscationSecret{}, ObfuscationSecret{}, errors.Trace(err)
+	}
+
+	return send, receive, nil
+}
+
 // obfuscateSessionPacket wraps a session packet with an obfuscation layer
 // which provides:
 //
@@ -149,44 +144,38 @@ func deriveSessionPacketObfuscationSecret(
 // anti-replay for nonces, this measure doen't cover the session handshake,
 // so an independent anti-replay mechanism is implemented here.
 func obfuscateSessionPacket(
-	rootObfuscationSecret ObfuscationSecret,
+	obfuscationSecret ObfuscationSecret,
 	isInitiator bool,
 	packet []byte,
 	paddingMin int,
 	paddingMax int) ([]byte, error) {
 
-	// For simplicity, the secret is derived here for each packet. Derived
-	// keys could be cached, but we need to be updated when a time factor is
-	// active. Typical in-proxy sessions will exchange only a handful of
-	// packets per event: the session handshake, and an API request round
-	// trip or two. We don't attempt to avoid allocations here.
-	//
-	// Benchmark for secret derivation:
-	//
-	//   BenchmarkDeriveObfuscationSecret
-	//   BenchmarkDeriveObfuscationSecret-8   	 1303953	       902.7 ns/op
+	obfuscatedPacket := make([]byte, obfuscationSessionPacketNonceSize)
 
-	key, err := deriveSessionPacketObfuscationSecret(
-		rootObfuscationSecret, isInitiator, true)
+	_, err := prng.Read(obfuscatedPacket[:])
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
 
-	obfuscatedPacket := make([]byte, obfuscationSessionPacketNonceSize)
+	// Initiators add a timestamp within the obfuscated packet. The responder
+	// uses this value to discard potentially replayed packets which are
+	// outside the time range of the reponder's anti-replay history.
 
-	_, err = prng.Read(obfuscatedPacket[:])
-	if err != nil {
-		return nil, errors.Trace(err)
+	// TODO: add a consistent (per-session), random offset to timestamps for
+	// privacy?
+
+	var timestampedPacket []byte
+	if isInitiator {
+		timestampedPacket = binary.AppendVarint(nil, time.Now().Unix())
 	}
 
-	var paddedPacket []byte
 	paddingSize := prng.Range(paddingMin, paddingMax)
-	paddedPacket = binary.AppendUvarint(paddedPacket, uint64(paddingSize))
+	paddedPacket := binary.AppendUvarint(timestampedPacket, uint64(paddingSize))
 
 	paddedPacket = append(paddedPacket, make([]byte, paddingSize)...)
 	paddedPacket = append(paddedPacket, packet...)
 
-	block, err := aes.NewCipher(key[:])
+	block, err := aes.NewCipher(obfuscationSecret[:])
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -214,7 +203,7 @@ func obfuscateSessionPacket(
 // an error: the obfuscated packet may have been created by a prober without
 // the correct secret; or replayed by a prober.
 func deobfuscateSessionPacket(
-	rootObfuscationSecret ObfuscationSecret,
+	obfuscationSecret ObfuscationSecret,
 	isInitiator bool,
 	replayHistory *obfuscationReplayHistory,
 	obfuscatedPacket []byte) ([]byte, error) {
@@ -243,16 +232,10 @@ func deobfuscateSessionPacket(
 		return nil, errors.TraceNew("replayed nonce")
 	}
 
-	key, err := deriveSessionPacketObfuscationSecret(
-		rootObfuscationSecret, isInitiator, false)
-	if err != nil {
-		return nil, errors.Trace(err)
-	}
-
 	// As an AEAD, AES-GCM authenticates that the sender used the expected
 	// key, and so has the root obfuscation secret.
 
-	block, err := aes.NewCipher(key[:])
+	block, err := aes.NewCipher(obfuscationSecret[:])
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -271,7 +254,16 @@ func deobfuscateSessionPacket(
 		return nil, errors.Trace(err)
 	}
 
+	n := 0
 	offset := 0
+	timestamp := int64(0)
+	if replayHistory != nil {
+		timestamp, n = binary.Varint(plaintext[offset:])
+		if n < 1 {
+			return nil, errors.TraceNew("invalid timestamp")
+		}
+		offset += n
+	}
 	paddingSize, n := binary.Uvarint(plaintext[offset:])
 	if n < 1 {
 		return nil, errors.TraceNew("invalid padding size")
@@ -284,6 +276,18 @@ func deobfuscateSessionPacket(
 
 	if replayHistory != nil {
 
+		// Accept the initiator's timestamp only if it's within +/-
+		// antiReplayTimeFactorPeriodSeconds/2 of the responder's clock. This
+		// step discards packets that are outside the range of the replay history.
+
+		now := time.Now().Unix()
+		if timestamp+antiReplayTimeFactorPeriodSeconds/2 < now {
+			return nil, errors.TraceNew("timestamp behind")
+		}
+		if timestamp-antiReplayTimeFactorPeriodSeconds/2 > now {
+			return nil, errors.TraceNew("timestamp ahead")
+		}
+
 		// Now that it's validated, add this packet to the replay history. The
 		// nonce is expected to be unique, so it's used as the history key.
 
@@ -318,7 +322,7 @@ func imitateDeobfuscateSessionPacketDuration(replayHistory *obfuscationReplayHis
 // obfuscationReplayHistory provides a lookup for recently observed obfuscated
 // session packet nonces. History is maintained for
 // 2*antiReplayTimeFactorPeriodSeconds; it's assumed that older packets, if
-// replayed, will fail to decrypt due to using an expired time factor.
+// replayed, will fail to deobfuscate due to using an expired timestamp.
 type obfuscationReplayHistory struct {
 	mutex         sync.Mutex
 	filters       [2]*cuckoo.Filter

+ 45 - 23
psiphon/common/inproxy/obfuscation_test.go

@@ -95,7 +95,7 @@ func runTestSessionPacketObfuscation() error {
 	// Use a replay time period factor more suitable for test runs.
 
 	originalAntiReplayTimeFactorPeriodSeconds := antiReplayTimeFactorPeriodSeconds
-	antiReplayTimeFactorPeriodSeconds = 1
+	antiReplayTimeFactorPeriodSeconds = 2
 	defer func() {
 		antiReplayTimeFactorPeriodSeconds = originalAntiReplayTimeFactorPeriodSeconds
 	}()
@@ -105,6 +105,18 @@ func runTestSessionPacketObfuscation() error {
 		return errors.Trace(err)
 	}
 
+	initiatorSendSecret, initiatorReceiveSecret, err :=
+		deriveSessionPacketObfuscationSecrets(rootSecret, true)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
+	responderSendSecret, responderReceiveSecret, err :=
+		deriveSessionPacketObfuscationSecrets(rootSecret, false)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
 	replayHistory := newObfuscationReplayHistory()
 
 	// Test: obfuscate/deobfuscate initiator -> responder
@@ -114,13 +126,13 @@ func runTestSessionPacketObfuscation() error {
 	maxPadding := 1000
 
 	obfuscatedPacket1, err := obfuscateSessionPacket(
-		rootSecret, true, packet, minPadding, maxPadding)
+		initiatorSendSecret, true, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
 
 	packet1, err := deobfuscateSessionPacket(
-		rootSecret, false, replayHistory, obfuscatedPacket1)
+		responderReceiveSecret, false, replayHistory, obfuscatedPacket1)
 	if err != nil {
 		return errors.Trace(err)
 	}
@@ -132,17 +144,17 @@ func runTestSessionPacketObfuscation() error {
 	// Test: replay packet
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, false, replayHistory, obfuscatedPacket1)
+		responderReceiveSecret, false, replayHistory, obfuscatedPacket1)
 	if err == nil {
 		return errors.TraceNew("unexpected replay success")
 	}
 
 	// Test: replay packet after time factor period
 
-	time.Sleep(1 * time.Second)
+	time.Sleep(time.Duration(antiReplayTimeFactorPeriodSeconds) * time.Second)
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, false, replayHistory, obfuscatedPacket1)
+		responderReceiveSecret, false, replayHistory, obfuscatedPacket1)
 	if err == nil {
 		return errors.TraceNew("unexpected replay success")
 	}
@@ -152,7 +164,7 @@ func runTestSessionPacketObfuscation() error {
 	n := 10
 	for i := 0; i < n; i++ {
 		obfuscatedPacket2, err := obfuscateSessionPacket(
-			rootSecret, true, packet, minPadding, maxPadding)
+			initiatorSendSecret, true, packet, minPadding, maxPadding)
 		if err != nil {
 			return errors.Trace(err)
 		}
@@ -167,13 +179,13 @@ func runTestSessionPacketObfuscation() error {
 	// Test: obfuscate/deobfuscate responder -> initiator
 
 	obfuscatedPacket2, err := obfuscateSessionPacket(
-		rootSecret, false, packet, minPadding, maxPadding)
+		responderSendSecret, false, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
 
 	packet2, err := deobfuscateSessionPacket(
-		rootSecret, true, nil, obfuscatedPacket2)
+		initiatorReceiveSecret, true, nil, obfuscatedPacket2)
 	if err != nil {
 		return errors.Trace(err)
 	}
@@ -185,13 +197,13 @@ func runTestSessionPacketObfuscation() error {
 	// Test: initiator -> initiator
 
 	obfuscatedPacket1, err = obfuscateSessionPacket(
-		rootSecret, true, packet, minPadding, maxPadding)
+		initiatorSendSecret, true, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, true, nil, obfuscatedPacket1)
+		initiatorReceiveSecret, true, nil, obfuscatedPacket1)
 	if err == nil {
 		return errors.TraceNew("unexpected initiator -> initiator success")
 	}
@@ -199,15 +211,15 @@ func runTestSessionPacketObfuscation() error {
 	// Test: responder -> responder
 
 	obfuscatedPacket2, err = obfuscateSessionPacket(
-		rootSecret, false, packet, minPadding, maxPadding)
+		responderSendSecret, false, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, false, newObfuscationReplayHistory(), obfuscatedPacket2)
+		responderReceiveSecret, false, newObfuscationReplayHistory(), obfuscatedPacket2)
 	if err == nil {
-		return errors.TraceNew("unexpected initiator -> initiator success")
+		return errors.TraceNew("unexpected responder -> responder success")
 	}
 
 	// Test: distinct keys derived for each direction
@@ -237,13 +249,13 @@ func runTestSessionPacketObfuscation() error {
 	padding := 100
 
 	obfuscatedPacket1, err = obfuscateSessionPacket(
-		rootSecret, true, packet, padding, padding)
+		initiatorSendSecret, true, packet, padding, padding)
 	if err != nil {
 		return errors.Trace(err)
 	}
 
 	obfuscatedPacket2, err = obfuscateSessionPacket(
-		rootSecret, false, packet, padding, padding)
+		initiatorSendSecret, true, packet, padding, padding)
 	if err != nil {
 		return errors.Trace(err)
 	}
@@ -258,8 +270,12 @@ func runTestSessionPacketObfuscation() error {
 	for _, isInitiator := range []bool{true, false} {
 
 		err = testEntropy(func() ([]byte, error) {
+			secret := initiatorSendSecret
+			if !isInitiator {
+				secret = responderSendSecret
+			}
 			obfuscatedPacket, err := obfuscateSessionPacket(
-				rootSecret, isInitiator, packet, padding, padding)
+				secret, isInitiator, packet, padding, padding)
 			if err != nil {
 				return nil, errors.Trace(err)
 			}
@@ -277,14 +293,20 @@ func runTestSessionPacketObfuscation() error {
 		return errors.Trace(err)
 	}
 
+	wrongInitiatorSendSecret, _, err :=
+		deriveSessionPacketObfuscationSecrets(wrongRootSecret, true)
+	if err != nil {
+		return errors.Trace(err)
+	}
+
 	obfuscatedPacket1, err = obfuscateSessionPacket(
-		wrongRootSecret, true, packet, minPadding, maxPadding)
+		wrongInitiatorSendSecret, true, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, false, newObfuscationReplayHistory(), obfuscatedPacket1)
+		responderReceiveSecret, false, newObfuscationReplayHistory(), obfuscatedPacket1)
 	if err == nil {
 		return errors.TraceNew("unexpected wrong secret success")
 	}
@@ -292,7 +314,7 @@ func runTestSessionPacketObfuscation() error {
 	// Test: truncated obfuscated packet
 
 	obfuscatedPacket1, err = obfuscateSessionPacket(
-		rootSecret, true, packet, minPadding, maxPadding)
+		initiatorSendSecret, true, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
@@ -300,7 +322,7 @@ func runTestSessionPacketObfuscation() error {
 	obfuscatedPacket1 = obfuscatedPacket1[:len(obfuscatedPacket1)-1]
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, false, newObfuscationReplayHistory(), obfuscatedPacket1)
+		responderReceiveSecret, false, newObfuscationReplayHistory(), obfuscatedPacket1)
 	if err == nil {
 		return errors.TraceNew("unexpected truncated packet success")
 	}
@@ -308,7 +330,7 @@ func runTestSessionPacketObfuscation() error {
 	// Test: flip byte
 
 	obfuscatedPacket1, err = obfuscateSessionPacket(
-		rootSecret, true, packet, minPadding, maxPadding)
+		initiatorSendSecret, true, packet, minPadding, maxPadding)
 	if err != nil {
 		return errors.Trace(err)
 	}
@@ -316,7 +338,7 @@ func runTestSessionPacketObfuscation() error {
 	obfuscatedPacket1[len(obfuscatedPacket1)-1] ^= 1
 
 	_, err = deobfuscateSessionPacket(
-		rootSecret, false, newObfuscationReplayHistory(), obfuscatedPacket1)
+		responderReceiveSecret, false, newObfuscationReplayHistory(), obfuscatedPacket1)
 	if err == nil {
 		return errors.TraceNew("unexpected modified packet success")
 	}

+ 32 - 12
psiphon/common/inproxy/session.go

@@ -436,10 +436,18 @@ func (r *InitiatorRoundTrip) Next(
 		}
 
 		newSession := func() (*session, error) {
+
+			sendObfuscationSecret, receiveObfuscationSecret, err :=
+				deriveSessionPacketObfuscationSecrets(r.responderRootObfuscationSecret, false)
+			if err != nil {
+				return nil, errors.Trace(err)
+			}
+
 			session, err := newSession(
 				true, // isInitiator
 				r.initiatorSessions.privateKey,
-				r.responderRootObfuscationSecret,
+				sendObfuscationSecret,
+				receiveObfuscationSecret,
 				nil, // No obfuscation replay history
 				&r.responderPublicKey,
 				r.requestPayload,
@@ -633,7 +641,8 @@ func (r *InitiatorRoundTrip) Response() ([]byte, error) {
 // supported.
 type ResponderSessions struct {
 	privateKey                  SessionPrivateKey
-	rootObfuscationSecret       ObfuscationSecret
+	sendObfuscationSecret       ObfuscationSecret
+	receiveObfuscationSecret    ObfuscationSecret
 	applyTTL                    bool
 	obfuscationReplayHistory    *obfuscationReplayHistory
 	expectedInitiatorPublicKeys sessionPublicKeyLookup
@@ -648,9 +657,16 @@ func NewResponderSessions(
 	responderPrivateKey SessionPrivateKey,
 	responderRootObfuscationSecret ObfuscationSecret) (*ResponderSessions, error) {
 
+	sendObfuscationSecret, receiveObfuscationSecret, err :=
+		deriveSessionPacketObfuscationSecrets(responderRootObfuscationSecret, true)
+	if err != nil {
+		return nil, errors.Trace(err)
+	}
+
 	return &ResponderSessions{
 		privateKey:               responderPrivateKey,
-		rootObfuscationSecret:    responderRootObfuscationSecret,
+		sendObfuscationSecret:    sendObfuscationSecret,
+		receiveObfuscationSecret: receiveObfuscationSecret,
 		applyTTL:                 true,
 		obfuscationReplayHistory: newObfuscationReplayHistory(),
 		sessions:                 lrucache.NewWithLRU(sessionsTTL, 1*time.Minute, sessionsMaxSize),
@@ -737,7 +753,7 @@ func (s *ResponderSessions) HandlePacket(
 	// request and that will be handled below.
 
 	sessionPacket, err := unwrapSessionPacket(
-		s.rootObfuscationSecret, false, s.obfuscationReplayHistory, inPacket)
+		s.receiveObfuscationSecret, false, s.obfuscationReplayHistory, inPacket)
 	if err != nil {
 		return nil, errors.Trace(err)
 	}
@@ -899,7 +915,8 @@ func (s *ResponderSessions) getSession(sessionID ID) (*session, error) {
 	session, err := newSession(
 		false, // !isInitiator
 		s.privateKey,
-		s.rootObfuscationSecret,
+		s.sendObfuscationSecret,
+		s.receiveObfuscationSecret,
 		s.obfuscationReplayHistory,
 		nil,
 		nil,
@@ -989,7 +1006,8 @@ type sessionLookup map[SessionPublicKey]*session
 type session struct {
 	isInitiator                 bool
 	sessionID                   ID
-	rootObfuscationSecret       ObfuscationSecret
+	sendObfuscationSecret       ObfuscationSecret
+	receiveObfuscationSecret    ObfuscationSecret
 	replayHistory               *obfuscationReplayHistory
 	expectedInitiatorPublicKeys sessionPublicKeyLookup
 
@@ -1007,7 +1025,8 @@ type session struct {
 func newSession(
 	isInitiator bool,
 	privateKey SessionPrivateKey,
-	rootObfuscationSecret ObfuscationSecret,
+	sendObfuscationSecret ObfuscationSecret,
+	receiveObfuscationSecret ObfuscationSecret,
 	replayHistory *obfuscationReplayHistory,
 
 	// Initiator
@@ -1089,7 +1108,8 @@ func newSession(
 	return &session{
 		isInitiator:                 isInitiator,
 		sessionID:                   *sessionID,
-		rootObfuscationSecret:       rootObfuscationSecret,
+		sendObfuscationSecret:       sendObfuscationSecret,
+		receiveObfuscationSecret:    receiveObfuscationSecret,
 		replayHistory:               replayHistory,
 		expectedInitiatorPublicKeys: expectedInitiatorPublicKeys,
 		state:                       state,
@@ -1457,7 +1477,7 @@ func (s *session) wrapPacket(sessionPacket *SessionPacket) ([]byte, error) {
 	}
 
 	obfuscatedPacket, err := obfuscateSessionPacket(
-		s.rootObfuscationSecret,
+		s.sendObfuscationSecret,
 		s.isInitiator,
 		marshaledPacket,
 		sessionObfuscationPaddingMinSize,
@@ -1476,7 +1496,7 @@ func (s *session) unwrapPacket(obfuscatedPacket []byte) (*SessionPacket, error)
 	// No lock. References only static session fields.
 
 	sessionPacket, err := unwrapSessionPacket(
-		s.rootObfuscationSecret,
+		s.receiveObfuscationSecret,
 		s.isInitiator,
 		s.replayHistory,
 		obfuscatedPacket)
@@ -1492,13 +1512,13 @@ func (s *session) unwrapPacket(obfuscatedPacket []byte) (*SessionPacket, error)
 // responders, which must peak at the SessionPacket and get the session ID to
 // route packets to the correct session.
 func unwrapSessionPacket(
-	rootObfuscationSecret ObfuscationSecret,
+	receiveObfuscationSecret ObfuscationSecret,
 	isInitiator bool,
 	replayHistory *obfuscationReplayHistory,
 	obfuscatedPacket []byte) (*SessionPacket, error) {
 
 	packet, err := deobfuscateSessionPacket(
-		rootObfuscationSecret,
+		receiveObfuscationSecret,
 		isInitiator,
 		replayHistory,
 		obfuscatedPacket)

+ 1 - 1
psiphon/common/inproxy/session_test.go

@@ -161,7 +161,7 @@ func runTestSessions() error {
 
 	unknownInitiatorSessions := NewInitiatorSessions(unknownInitiatorPrivateKey)
 
-	ctx, cancelFunc := context.WithTimeout(context.Background(), 10*time.Millisecond)
+	ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second)
 	defer cancelFunc()
 
 	request = roundTripper.MakeRequest()

+ 1 - 1
psiphon/common/inproxy/webrtc.go

@@ -158,7 +158,7 @@ func newWebRTCConn(
 	if config.DoDTLSRandomization {
 
 		dtlsObfuscationSecret, err := deriveObfuscationSecret(
-			config.ClientRootObfuscationSecret, false, "in-proxy-DTLS-seed")
+			config.ClientRootObfuscationSecret, "in-proxy-DTLS-seed")
 		if err != nil {
 			return nil, nil, nil, errors.Trace(err)
 		}