otrv4 / libotr-ng

A new implementation of OTR with support for version 4. This is a mirror of https://bugs.otr.im/otrv4/libotr-ng
Other
43 stars 9 forks source link

How are timers going to work? (related to session expiration) #194

Closed claucece closed 5 years ago

claucece commented 5 years ago

The current functionality of the session expiration asks for an specific time, in order to expire the session:

  if (conv->conn->keys->last_generated < now - expiration_time) {
    if (otrng_failed(otrng_expire_session(new_msg, conv->conn))) {
      return OTRNG_ERROR;
    }
  }

The expiration time is handled by the client: is this going to be:

  1. a timer?
  2. just a time?

It is unsure how will this work from a UI perspective.. the session expiration sends a TLV type 1, meaning, that when the session expires, the user will have to manually start a new session.

In the past, libotr used a timer, as defined in #183 .

There are other things related to time that should be handled by a client: the expiration of the client profile, the expiration of the prekey profile, profiles_buffer_time, the extra valid time...

olabini commented 5 years ago

I'm not sure where I documented my thoughts on timers. But anyway, my thought is basically the same as what libotr is doing - provide a function that the client is supposed to call every X seconds. Inside of there we do all the things that needs to be done. For expiration of a session, you're right - in this case the user would have to manually start a new session. But I don't think this will be a very common occurrence, right?

Where did the idea of session expiration come from anyway? OTRv3 doesn't have it, right?

claucece commented 5 years ago

For expiration of a session, you're right - in this case the user would have to manually start a new session. But I don't think this will be a very common occurrence, right?

It depends. A client can decide that it is every '5 minutes', then, the session will be ended. What can be done is expiring the session; but also send a query or something to restart.

Where did the idea of session expiration come from anyway? OTRv3 doesn't have it, right?

From Nik, due to the incorporation of the non-interactive path. From the spec:

Second, to fully defend against attack 2, sessions are expired if no new ECDH keys are generated 
within a certain amount of time. This encourages keys to be removed often at the cost of lost 
messages whose MAC keys cannot be revealed. For example, when Alice sets her session expiration 
time to be 2 hours, Bob must reply within that time and Alice must create a response to his reply (thus
 generating a new ECDH key) in order to reset the session expiration time for Alice. If Alice does not 
generate a new ECDH key in two hours, Alice will delete all keys associated with this session. If she 
receives a message from Bob using the expired session, she cannot decrypt the message and thus she 
cannot reveal the MAC key associated with it.

This session time is decided individually by each participant or by the client they use so it is possible
 for Alice to have an expiration time of two hours and Bob two weeks. In addition, for the first data 
message only, the receiver will start their expiration timer once the message is received. The reason 
why we use a timer and don't count events is that we are trying to determine whether something has 
not happened within a certain time frame. Thus, the timer can be compromised by clock errors. Some errors may cause the session to be deleted too early and result in undecryptable messages being 
received. Other errors may result in the clock not moving forward which would cause a session to 
never expire. To mitigate this, implementers should use secure and reliable clocks that cannot be 
manipulated by an attacker.

The OTRv4 spec will give implementers a guide to determine the amount of time for session expiration.
 It is difficult to dictate a good general expiration time since many secure messaging scenarios exist
 with different security requirements. The session expiration is essentially an expiration on the last 
message's readability and deniability. The time setter (either the implementer or the user) should 
expect that replies are unreadable and undeniable after this time. For example, if the time is set to 15
 minutes, messages received after 15 minutes are unreadable and undeniable, but an attacker must 
compromise the local keys within 15 minutes in order to read and tamper with the last message sent
 before that time passes. If the time is set to one month, this allows the receiver to reply within one
 month. However, if the client is compromised within one month, an attacker is able to read and tamper
 with the last message sent.

The attack is:

Initiator and Responder complete an exchange and engage in a conversation. At some point, the
 adversary captures and drops some messages to (for example) Initiator. Later, the adversary 
compromises Initiator's ephemeral secrets, revealing the message keys corresponding to the dropped
 messages. The adversary can now retroactively decrypt the captured messages.
olabini commented 5 years ago

It depends. A client can decide that it is every '5 minutes', then, the session will be ended. What can be done is expiring the session; but also send a query or something to restart.

I don't really understand this.

claucece commented 5 years ago

Let's talk tomorrow @olabini

olabini commented 5 years ago

OK, I think I fully understand all this stuff now.

First - the timer_control callback in libotr is not really a good idea for our use case, since we have many more things that need to be expired. We should have something like otrng_client_poll - and inside of that fragments will be expired, sessions will be expired, etc. The client can call this every 1 minute, or whatever time they want.

Expiring Prekey Profiles and Client Profiles I'm actually not too worried about, since that will happen on every call to orchestration anyway. Although we can do it in the poll function as well.

About the session expiration, my recommendation is that we add a new callback session_expiration_for - that will allow you to set custom expiration times for each peer. About what happens on expiration, we could have policies for that: ON_EXPIRE_DO_NOTHING, ON_EXPIRE_RESTART_WITH_IDENTITY, ON_EXPIRE_RESTART_WITH_QUERY, or something like that. Does this all make sense?

olabini commented 5 years ago

Do we have a separate issue for session expiration or should that be implemented as part of this issue?

olabini commented 5 years ago

I can go ahead and start implementing this if you feel it makes sense.

claucece commented 5 years ago

@olabini sounds good.

Do we have a separate issue for session expiration or should that be implemented as part of this issue?

We already have a method for it: it is already implemented. It basically sends a tlv disconnected.

olabini commented 5 years ago

Ah, perfect. so it should just be triggered from the timer.

I'll go ahead with implementing it.