Review Board 1.7.16


Add ability to reload SRTP policies

Review Request #1741 - Created Feb. 14, 2012 and submitted

Matt Jordan
1.8
Reviewers
asterisk-dev
file, mmichelson, otherwiseguy
Asterisk
Currently, when using res_srtp, once the SRTP policy has been added to the current session the policy is locked into place.  Any attempt to replace an existing policy, which would be needed if the remote endpoint negotiated a new cryptographic key, is instead rejected in res_srtp.  We thus need to have a mechanism to replace an existing policy associated with either a local or remote endpoint.

If we needed to change the key for a local policy (which we don't do, but its a hypothetical situation), changing the crytographic key is easy.  The old stream associated with the local SSRC is removed, and a new stream is added.  The libsrtp library has straightforward calls for this.

However, for the remote policy, it isn't as easy.  Because our remote policy uses a wildcard type to match on any inbound SSRC value, it can't be replaced.  The libsrtp library explicitly disallows changing wildcard policies (as the policies are applied to all streams matching the respective inbound/outbound direction, so replacing a wildcard policy would entail replacing all streams associated with that policy).  As such, the only thing that can be done is to deallocate the old session and create a new session.

The replaces one problem with another - while we can replace the old session with a new session and a new remote policy, we would effectively destroy our local policy / stream when we do that.  Currently, there is not an imposed order on when the local/remote policies are added (and in fact, we add the local one before the remote one currently).  Thus, when replacing an SRTP session with a new one, the order in which things are done has to be:
1) Destroy the old SRTP session
2) Create a new SRTP session and add one of the two policies
3) Add the other policy
If we don't add both policies at the same time, we could end up in a situation where we set the local policy, and then set the remote policy, blowing out the previously added local policy.  Good times.

This patch does the following:
1) It combines the adding of remote/local policies onto an SRTP session.  Although this changes the rtp_engine API, in effect its minor, as the two were always added at the same time anyway by users of the API.  This allows us to control the order in which things are added in res_srtp, and users of the API don't have to worry.
2) It adds a new virtual method to the res_srtp API, replace.  This combines the destroy/create methods.
3) We now check for the type of stream we are adding.  If we are adding a policy for a specific SSRC, we replace the existing stream.  If we are adding a policy for a wildcard, we bail out if we already have a policy existing for that wildcard; otherwise we add it.

This patch does some other cleanup in unprotect and unload module, including toning down the log statements and shutting down the libsrtp library on unload.
Made sure that the initial patch didn't break the SRTP test in the TestSuite.  Made sure that the module could be loaded and unloaded.

More testing is needed to make sure that the whole thing actually works.
Review request changed
Updated (Feb. 23, 2012, 3:32 a.m.)
Clarified the local/remote policy comment a bit.  I didn't modify the change to the SRTP API, as I still think its the correct way to fix this problem and prevent unintentionally adding the policies in the wrong order, thereby mucking up res_srtp.

Ran additional tests using a slightly beefier version of sip_srtp in the Asterisk Test Suite.  Confirmed that in a simple, nominal call setup between two UAs supporting SRTP, sessions are set up and torn down correctly, and that the RTP stream is protected/unprotected.

Testing by the issue reporter confirmed that the code change also works in a simple, nominal situation, and that it also properly handles changing of the remote policy by the endpoint during a blind transfer (which sent the re-INVITE with the new crypto key that caused this whole thing in the first place)
Ship it!
Posted (Feb. 23, 2012, 5:43 a.m.)
So this all looks fine to me.

I still think you could have gotten the change into 1.8 or 10 without changing the API call, but since it's highly unlikely anything out there is actually a consumer of the API, I suppose I can let this slide.

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.