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.
/branches/1.8/channels/sip/sdp_crypto.c
Revision 356289 New Change
[20] 158 lines
[+20] [+] static int sdp_crypto_activate(struct sdp_crypto *p, int suite_val, unsigned char *remote_key, struct ast_rtp_instance *rtp)
159

    
   
159

   
160
	if (set_crypto_policy(remote_policy, suite_val, remote_key, 0, 1) < 0) {
160
	if (set_crypto_policy(remote_policy, suite_val, remote_key, 0, 1) < 0) {
161
		goto err;
161
		goto err;
162
	}
162
	}
163

    
   
163

   
164
	/* FIXME MIKMA */
164
	/* Add the SRTP policies */
165
	/* ^^^ I wish I knew what needed fixing... */
165
	if (ast_rtp_instance_add_srtp_policy(rtp, remote_policy, local_policy)) {
166
	if (ast_rtp_instance_add_srtp_policy(rtp, local_policy)) {
166
		ast_log(LOG_WARNING, "Could not set SRTP policies\n");
167
		ast_log(LOG_WARNING, "Could not set local SRTP policy\n");

   
168
		goto err;

   
169
	}

   
170

    
   

   
171
	if (ast_rtp_instance_add_srtp_policy(rtp, remote_policy)) {

   
172
		ast_log(LOG_WARNING, "Could not set remote SRTP policy\n");

   
173
		goto err;
167
		goto err;
174
	}
168
	}
175

    
   
169

   
176
	ast_debug(1 , "SRTP policy activated\n");
170
	ast_debug(1 , "SRTP policy activated\n");
177
	res = 0;
171
	res = 0;
[+20] [20] 96 lines
[+20] [+] int sdp_crypto_process(struct sdp_crypto *p, const char *attr, struct ast_rtp_instance *rtp)
274
	if (!p->a_crypto) {
268
	if (!p->a_crypto) {
275
		if (!(p->a_crypto = ast_calloc(1, attr_len + 11))) {
269
		if (!(p->a_crypto = ast_calloc(1, attr_len + 11))) {
276
			ast_log(LOG_ERROR, "Could not allocate memory for a_crypto\n");
270
			ast_log(LOG_ERROR, "Could not allocate memory for a_crypto\n");
277
			return -1;
271
			return -1;
278
		}
272
		}
279

    
   

   
280
		snprintf(p->a_crypto, attr_len + 10, "a=crypto:%s %s inline:%s\r\n", tag, suite, p->local_key64);
273
		snprintf(p->a_crypto, attr_len + 10, "a=crypto:%s %s inline:%s\r\n", tag, suite, p->local_key64);
281
	}
274
	}
282

    
   

   
283
	return 0;
275
	return 0;
284
}
276
}
285

    
   
277

   
286
int sdp_crypto_offer(struct sdp_crypto *p)
278
int sdp_crypto_offer(struct sdp_crypto *p)
287
{
279
{
[+20] [20] 22 lines
/branches/1.8/include/asterisk/res_srtp.h
Revision 356289 New Change
 
/branches/1.8/include/asterisk/rtp_engine.h
Revision 356289 New Change
 
/branches/1.8/main/rtp_engine.c
Revision 356289 New Change
 
/branches/1.8/res/res_srtp.c
Revision 356289 New Change
 
  1. /branches/1.8/channels/sip/sdp_crypto.c: Loading...
  2. /branches/1.8/include/asterisk/res_srtp.h: Loading...
  3. /branches/1.8/include/asterisk/rtp_engine.h: Loading...
  4. /branches/1.8/main/rtp_engine.c: Loading...
  5. /branches/1.8/res/res_srtp.c: Loading...

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.