[asterisk-dev] AstriDevCon Recap - IAX2 RENEW for encryption
Russell Bryant
russell at digium.com
Thu May 31 09:14:47 MST 2007
Greetings,
One of the topics discussed at the developer conference was the method
used for IAX2 encryption. We wanted to ensure that the method we are
using is actually secure. I have summarized what came out of the
discussion below. Comments are welcome, as always.
From this discussion, we need to make two changes. One is an
implementation issue, and the other is a protocol level issue. The
protocol level issue needs to get resolved quickly so that we can get it
in the first version of the RFC, since IAX2 encryption is in there.
1) We should use a better random number generator. Most of the places
in Asterisk are using the ast_random() wrapper, so changing the method
in one place should affect every usage.
Currently, we use random(), which is better than rand(), but we seed it
with the process ID and time. We should just change the code to open
and read from /dev/urandom where it is available.
2) This issue is related to the key used for encryption. Here is a
basic rundown on how it works right now:
a) ====== NEW =====> (not encrypted)
A NEW packet is sent to initiate a call, and this message contains the
ENCRYPTION information element to indicate which methods of IAX2
encryption are supported for this call.
b) <===== AUTHREQ ===== (not encrypted)
An AUTHREQ is sent to request authentication for the call. In this
message, there are two information elements related to encryption for
the call.
The first is the ENCRYPTION information element. If this is present, it
contains a single encryption method that the peer has agreed to use for
the call (Currently, only AES128 is defined for use).
The other is the CHALLENGE information element. This contains random
data. The encryption key that both sides will begin using is the MD5
hash of this challenge and the shared secret.
c) ====== AUTHREP =====> (encrypted)
This message is sent with the authentication credentials as normal.
However, it is encrypted with the key generated by taking the MD5 hash
of the CHALLENGE and the shared secret.
If the incorrect key is used, the other side will get invalid data when
it tries to decrypt this message.
d) ... Rest of the call ... (encrypted)
Now, here is where a change needs to be made. Once the call is
established, there is no way to change the key being used. An
information element, ENCKEY has been defined for containing a new
encryption key, but there is no message that this information element
can be sent in. To resolve this, we can do the following:
Add a new IAX message type, RENEW, that can be sent during a call. If a
RENEW is received during an encrypted call and contains the ENCKEY
information element, immediately change the key used to decrypt the
traffic coming from the other side to use this key.
A RENEW can be explicitly acknowledged by a peer using an ACK, or it can
be implicitly acknowledged by the peer sending its own RENEW. Also, it
should be noted as a best practice to send a RENEW as soon as the call
is established, as well as every few minutes. (I chose a few minutes
here arbitrarily. If you have more insight into what would be a good
choice here, please let me know!)
e) Transfers
Transfers are a more complicated situation. The current RFC draft does
not address how to handle transfers involving encrypted sessions. Here
is what we came up with for this.
First of all, a transfer should not even be attempted unless both legs
involved in the transfer are using the same encryption method.
When a TXREL or TXMEDIA is sent to release the entire stream or just the
media, it should contain the ENCKEY information element. The key sent
here will be the key that the peer should use to decrypt the packets
received from the other end of the call.
--
Russell Bryant
Software Engineer
Digium, Inc.
More information about the asterisk-dev
mailing list