diff --git a/srtp/srtp.c b/srtp/srtp.c index 14d3c5fec4fdc44d5ff077d25bd7669b37b88580..abaccf45f0dfdeca46bb3e7a76a3cbe68d1fc8c2 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -147,53 +147,141 @@ unsigned int srtp_get_version() return rv; } -/* Release (maybe partially allocated) stream. */ -static void srtp_stream_free(srtp_stream_ctx_t *str) +srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream, + const srtp_stream_ctx_t *stream_template) { + srtp_err_status_t status; unsigned int i = 0; srtp_session_keys_t *session_keys = NULL; + srtp_session_keys_t *template_session_keys = NULL; - if (str->session_keys) { - for (i = 0; i < str->num_master_keys; i++) { - session_keys = &str->session_keys[i]; + /* + * we use a conservative deallocation strategy - if any deallocation + * fails, then we report that fact without trying to deallocate + * anything else + */ + if (stream->session_keys) { + for (i = 0; i < stream->num_master_keys; i++) { + session_keys = &stream->session_keys[i]; - if (session_keys->rtp_xtn_hdr_cipher) { - srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); + if (stream_template) { + template_session_keys = &stream_template->session_keys[i]; + } else { + template_session_keys = NULL; } - if (session_keys->rtcp_cipher) { - srtp_cipher_dealloc(session_keys->rtcp_cipher); + /* + * deallocate cipher, if it is not the same as that in template + */ + if (template_session_keys && + session_keys->rtp_cipher == template_session_keys->rtp_cipher) { + /* do nothing */ + } else if (session_keys->rtp_cipher) { + status = srtp_cipher_dealloc(session_keys->rtp_cipher); + if (status) + return status; + } + + /* + * deallocate auth function, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->rtp_auth == template_session_keys->rtp_auth) { + /* do nothing */ + } else if (session_keys->rtp_auth) { + status = srtp_auth_dealloc(session_keys->rtp_auth); + if (status) + return status; } - if (session_keys->rtcp_auth) { - srtp_auth_dealloc(session_keys->rtcp_auth); + if (template_session_keys && + session_keys->rtp_xtn_hdr_cipher == + template_session_keys->rtp_xtn_hdr_cipher) { + /* do nothing */ + } else if (session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); + if (status) + return status; } - if (session_keys->rtp_cipher) { - srtp_cipher_dealloc(session_keys->rtp_cipher); + /* + * deallocate rtcp cipher, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->rtcp_cipher == + template_session_keys->rtcp_cipher) { + /* do nothing */ + } else if (session_keys->rtcp_cipher) { + status = srtp_cipher_dealloc(session_keys->rtcp_cipher); + if (status) + return status; } - if (session_keys->rtp_auth) { - srtp_auth_dealloc(session_keys->rtp_auth); + /* + * deallocate rtcp auth function, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->rtcp_auth == template_session_keys->rtcp_auth) { + /* do nothing */ + } else if (session_keys->rtcp_auth) { + status = srtp_auth_dealloc(session_keys->rtcp_auth); + if (status) + return status; } + /* + * zeroize the salt value + */ + octet_string_set_to_zero(session_keys->salt, SRTP_AEAD_SALT_LEN); + octet_string_set_to_zero(session_keys->c_salt, SRTP_AEAD_SALT_LEN); + if (session_keys->mki_id) { + octet_string_set_to_zero(session_keys->mki_id, + session_keys->mki_size); srtp_crypto_free(session_keys->mki_id); + session_keys->mki_id = NULL; } - if (session_keys->limit) { + /* + * deallocate key usage limit, if it is not the same as that in + * template + */ + if (template_session_keys && + session_keys->limit == template_session_keys->limit) { + /* do nothing */ + } else if (session_keys->limit) { srtp_crypto_free(session_keys->limit); } } + } - srtp_crypto_free(str->session_keys); + if (stream_template && + stream->session_keys == stream_template->session_keys) { + /* do nothing */ + } else { + srtp_crypto_free(stream->session_keys); } - if (str->enc_xtn_hdr) { - srtp_crypto_free(str->enc_xtn_hdr); + status = srtp_rdbx_dealloc(&stream->rtp_rdbx); + if (status) + return status; + + /* DAM - need to deallocate EKT here */ + + if (stream_template && + stream->enc_xtn_hdr == stream_template->enc_xtn_hdr) { + /* do nothing */ + } else if (stream->enc_xtn_hdr) { + srtp_crypto_free(stream->enc_xtn_hdr); } - srtp_crypto_free(str); + /* deallocate srtp stream context */ + srtp_crypto_free(stream); + + return srtp_err_status_ok; } srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, @@ -233,7 +321,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, sizeof(srtp_session_keys_t) * str->num_master_keys); if (str->session_keys == NULL) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return srtp_err_status_alloc_fail; } @@ -245,7 +333,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, p->rtp.cipher_type, &session_keys->rtp_cipher, p->rtp.cipher_key_len, p->rtp.auth_tag_len); if (stat) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return stat; } @@ -254,7 +342,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, p->rtp.auth_type, &session_keys->rtp_auth, p->rtp.auth_key_len, p->rtp.auth_tag_len); if (stat) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return stat; } @@ -266,7 +354,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, p->rtcp.cipher_type, &session_keys->rtcp_cipher, p->rtcp.cipher_key_len, p->rtcp.auth_tag_len); if (stat) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return stat; } @@ -275,7 +363,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, p->rtcp.auth_type, &session_keys->rtcp_auth, p->rtcp.auth_key_len, p->rtcp.auth_tag_len); if (stat) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return stat; } @@ -285,7 +373,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, session_keys->limit = (srtp_key_limit_ctx_t *)srtp_crypto_alloc( sizeof(srtp_key_limit_ctx_t)); if (session_keys->limit == NULL) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return srtp_err_status_alloc_fail; } } @@ -293,7 +381,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, /* allocate ekt data associated with stream */ stat = srtp_ekt_alloc(&str->ekt, p->ekt); if (stat) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return stat; } @@ -304,7 +392,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, str->enc_xtn_hdr = (int *)srtp_crypto_alloc(p->enc_xtn_hdr_count * sizeof(p->enc_xtn_hdr[0])); if (!str->enc_xtn_hdr) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return srtp_err_status_alloc_fail; } memcpy(str->enc_xtn_hdr, p->enc_xtn_hdr, @@ -338,7 +426,7 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, enc_xtn_hdr_cipher_type, &session_keys->rtp_xtn_hdr_cipher, enc_xtn_hdr_cipher_key_len, 0); if (stat) { - srtp_stream_free(str); + srtp_stream_dealloc(str, NULL); return stat; } } @@ -355,138 +443,6 @@ srtp_err_status_t srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, return srtp_err_status_ok; } -srtp_err_status_t srtp_stream_dealloc(srtp_stream_ctx_t *stream, - srtp_stream_ctx_t *stream_template) -{ - srtp_err_status_t status; - unsigned int i = 0; - srtp_session_keys_t *session_keys = NULL; - srtp_session_keys_t *template_session_keys = NULL; - - /* - * we use a conservative deallocation strategy - if any deallocation - * fails, then we report that fact without trying to deallocate - * anything else - */ - for (i = 0; i < stream->num_master_keys; i++) { - session_keys = &stream->session_keys[i]; - - if (stream_template) { - template_session_keys = &stream_template->session_keys[i]; - } else { - template_session_keys = NULL; - } - - /* - * deallocate cipher, if it is not the same as that in template - */ - if (template_session_keys && - session_keys->rtp_cipher == template_session_keys->rtp_cipher) { - /* do nothing */ - } else { - status = srtp_cipher_dealloc(session_keys->rtp_cipher); - if (status) - return status; - } - - /* - * deallocate auth function, if it is not the same as that in template - */ - if (template_session_keys && - session_keys->rtp_auth == template_session_keys->rtp_auth) { - /* do nothing */ - } else { - status = srtp_auth_dealloc(session_keys->rtp_auth); - if (status) - return status; - } - - if (template_session_keys && - session_keys->rtp_xtn_hdr_cipher == - template_session_keys->rtp_xtn_hdr_cipher) { - /* do nothing */ - } else if (session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); - if (status) - return status; - } - - /* - * deallocate rtcp cipher, if it is not the same as that in - * template - */ - if (template_session_keys && - session_keys->rtcp_cipher == template_session_keys->rtcp_cipher) { - /* do nothing */ - } else { - status = srtp_cipher_dealloc(session_keys->rtcp_cipher); - if (status) - return status; - } - - /* - * deallocate rtcp auth function, if it is not the same as that in - * template - */ - if (template_session_keys && - session_keys->rtcp_auth == template_session_keys->rtcp_auth) { - /* do nothing */ - } else { - status = srtp_auth_dealloc(session_keys->rtcp_auth); - if (status) - return status; - } - - /* - * zeroize the salt value - */ - octet_string_set_to_zero(session_keys->salt, SRTP_AEAD_SALT_LEN); - octet_string_set_to_zero(session_keys->c_salt, SRTP_AEAD_SALT_LEN); - - if (session_keys->mki_id) { - octet_string_set_to_zero(session_keys->mki_id, - session_keys->mki_size); - srtp_crypto_free(session_keys->mki_id); - session_keys->mki_id = NULL; - } - - /* - * deallocate key usage limit, if it is not the same as that in template - */ - if (template_session_keys && - session_keys->limit == template_session_keys->limit) { - /* do nothing */ - } else { - srtp_crypto_free(session_keys->limit); - } - } - - if (stream_template && - stream->session_keys == stream_template->session_keys) { - /* do nothing */ - } else { - srtp_crypto_free(stream->session_keys); - } - - status = srtp_rdbx_dealloc(&stream->rtp_rdbx); - if (status) - return status; - - /* DAM - need to deallocate EKT here */ - - if (stream_template && - stream->enc_xtn_hdr == stream_template->enc_xtn_hdr) { - /* do nothing */ - } else if (stream->enc_xtn_hdr) { - srtp_crypto_free(stream->enc_xtn_hdr); - } - - /* deallocate srtp stream context */ - srtp_crypto_free(stream); - - return srtp_err_status_ok; -} - /* * srtp_stream_clone(stream_template, new) allocates a new stream and * initializes it using the cipher and auth of the stream_template @@ -518,7 +474,7 @@ srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template, sizeof(srtp_session_keys_t) * str->num_master_keys); if (str->session_keys == NULL) { - srtp_stream_free(*str_ptr); + srtp_stream_dealloc(*str_ptr, stream_template); *str_ptr = NULL; return srtp_err_status_alloc_fail; } @@ -543,7 +499,7 @@ srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template, srtp_crypto_alloc(template_session_keys->mki_size); if (session_keys->mki_id == NULL) { - srtp_stream_free(*str_ptr); + srtp_stream_dealloc(*str_ptr, stream_template); *str_ptr = NULL; return srtp_err_status_init_fail; } @@ -560,7 +516,7 @@ srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template, status = srtp_key_limit_clone(template_session_keys->limit, &session_keys->limit); if (status) { - srtp_stream_free(*str_ptr); + srtp_stream_dealloc(*str_ptr, stream_template); *str_ptr = NULL; return status; } @@ -570,7 +526,7 @@ srtp_err_status_t srtp_stream_clone(const srtp_stream_ctx_t *stream_template, status = srtp_rdbx_init( &str->rtp_rdbx, srtp_rdbx_get_window_size(&stream_template->rtp_rdbx)); if (status) { - srtp_stream_free(*str_ptr); + srtp_stream_dealloc(*str_ptr, stream_template); *str_ptr = NULL; return status; } @@ -2891,7 +2847,7 @@ srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy) /* initialize stream */ status = srtp_stream_init(tmp, policy); if (status) { - srtp_stream_free(tmp); + srtp_stream_dealloc(tmp, NULL); return status; } @@ -2906,7 +2862,7 @@ srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy) switch (policy->ssrc.type) { case (ssrc_any_outbound): if (session->stream_template) { - srtp_stream_free(tmp); + srtp_stream_dealloc(tmp, NULL); return srtp_err_status_bad_param; } session->stream_template = tmp; @@ -2914,7 +2870,7 @@ srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy) break; case (ssrc_any_inbound): if (session->stream_template) { - srtp_stream_free(tmp); + srtp_stream_dealloc(tmp, NULL); return srtp_err_status_bad_param; } session->stream_template = tmp; @@ -2926,7 +2882,7 @@ srtp_err_status_t srtp_add_stream(srtp_t session, const srtp_policy_t *policy) break; case (ssrc_undefined): default: - srtp_stream_free(tmp); + srtp_stream_dealloc(tmp, NULL); return srtp_err_status_bad_param; }