From fe5d8b82702174eb1f6a3e945fbc8ec4a529175c Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Thu, 15 Dec 2016 14:53:58 -0500 Subject: [PATCH 01/10] Apply MKI Support Patch --- Makefile.in | 2 +- include/srtp.h | 224 +++++++++- include/srtp_priv.h | 37 +- srtp/srtp.c | 920 +++++++++++++++++++++++++++------------- test/dtls_srtp_driver.c | 3 +- test/rtp_decoder.c | 3 +- test/rtpw.c | 4 +- test/srtp_driver.c | 453 +++++++++++++++++--- test/util.c | 15 + test/util.h | 6 + 10 files changed, 1298 insertions(+), 369 deletions(-) diff --git a/Makefile.in b/Makefile.in index f1773cff5..7e3dc284f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -189,7 +189,7 @@ test/srtp_driver$(EXE): test/srtp_driver.c test/util.c test/getopt_s.c test/rdbx_driver$(EXE): test/rdbx_driver.c test/getopt_s.c $(COMPILE) $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB) -test/dtls_srtp_driver$(EXE): test/dtls_srtp_driver.c test/getopt_s.c +test/dtls_srtp_driver$(EXE): test/dtls_srtp_driver.c test/getopt_s.c test/util.c $(COMPILE) $(LDFLAGS) -o $@ $^ $(LIBS) $(SRTPLIB) crypto/test/cipher_driver$(EXE): crypto/test/cipher_driver.c test/getopt_s.c diff --git a/include/srtp.h b/include/srtp.h index 515582d5b..5401be364 100644 --- a/include/srtp.h +++ b/include/srtp.h @@ -88,6 +88,14 @@ extern "C" { */ #define SRTP_MAX_TRAILER_LEN SRTP_MAX_TAG_LEN +/** + * SRTP_MAX_NUM_MASTER_KEYS is the maximum number of Master keys for + * MKI supported by libSRTP. Can look at making this dynamic in the + * future. + * + */ +#define SRTP_MAX_NUM_MASTER_KEYS 4 + /* * SRTP_AEAD_SALT_LEN is the length of the SALT values used with * GCM mode. GCM mode requires an IV. The SALT value is used @@ -267,7 +275,8 @@ typedef enum { srtp_err_status_parse_err = 21, /**< error parsing data */ srtp_err_status_encode_err = 22, /**< error encoding data */ srtp_err_status_semaphore_err = 23,/**< error while using semaphores */ - srtp_err_status_pfkey_err = 24 /**< error while using pfkey */ + srtp_err_status_pfkey_err = 24, /**< error while using pfkey */ + srtp_err_status_bad_mki = 25 /**< error MKI present in packet is invalid */ } srtp_err_status_t; typedef struct srtp_stream_ctx_t_ srtp_stream_ctx_t; @@ -364,6 +373,17 @@ typedef struct srtp_ekt_policy_ctx_t *srtp_ekt_policy_t; */ typedef struct srtp_ekt_stream_ctx_t *srtp_ekt_stream_t; +/** + * @brief srtp_master_key_t represents a master key. There will + * be a Master Key Index and the Master Key associated with the + * Master Key Index. Need to also keep track of the Master Key + * Index Size to correctly read it from a packet. + */ +typedef struct srtp_master_key_t { + unsigned char *key; + unsigned char *mki_id; + unsigned int mki_size; +} srtp_master_key_t; /** * @brief represents the policy for an SRTP session. @@ -400,8 +420,8 @@ typedef struct srtp_policy_t { */ srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ - unsigned char *key; /**< Pointer to the SRTP master key for - * this stream. */ + srtp_master_key_t keys[SRTP_MAX_NUM_MASTER_KEYS]; /** Array of Master Key structures */ + unsigned long num_master_keys; /** Number of master keys */ srtp_ekt_policy_t ekt; /**< Pointer to the EKT policy structure * for this stream (if any) */ unsigned long window_size; /**< The window size to use for replay @@ -511,6 +531,57 @@ srtp_err_status_t srtp_shutdown(void); */ srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); + +/** + * @brief srtp_protect_mki() is the Secure RTP sender-side packet processing + * function that can utilize MKI. + * + * The function call srtp_protect(ctx, rtp_hdr, len_ptr) applies SRTP + * protection to the RTP packet rtp_hdr (which has length *len_ptr) using + * the SRTP context ctx. If srtp_err_status_ok is returned, then rtp_hdr + * points to the resulting SRTP packet and *len_ptr is the number of + * octets in that packet; otherwise, no assumptions should be made + * about the value of either data elements. + * + * The sequence numbers of the RTP packets presented to this function + * need not be consecutive, but they @b must be out of order by less + * than 2^15 = 32,768 packets. + * + * @warning This function assumes that it can write the authentication + * tag into the location in memory immediately following the RTP + * packet, and assumes that the RTP packet is aligned on a 32-bit + * boundary. + * + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN + * into the location in memory immediately following the RTP packet. + * Callers MUST ensure that this much writable memory is available in + * the buffer that holds the RTP packet. + * + * @param ctx is the SRTP context to use in processing the packet. + * + * @param rtp_hdr is a pointer to the RTP packet (before the call); after + * the function returns, it points to the srtp packet. + * + * @param len_ptr is a pointer to the length in octets of the complete + * RTP packet (header and body) before the function call, and of the + * complete SRTP packet after the call, if srtp_err_status_ok was returned. + * Otherwise, the value of the data to which it points is undefined. + * + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true will + * use the session keys identified by the mki_index + * + * @param mki_index integer value specifying which set of session kesy should be + * used if use_mki is set to true. + * + * @return + * - srtp_err_status_ok no problems + * - srtp_err_status_replay_fail rtp sequence number was non-increasing + * - @e other failure in cryptographic mechanisms + */ + +srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len, + unsigned int use_mki, unsigned int mki_index); /** * @brief srtp_unprotect() is the Secure RTP receiver-side packet @@ -555,6 +626,49 @@ srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); srtp_err_status_t srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr); +/** + * @brief srtp_unprotect_mki() is the Secure RTP receiver-side packet + * processing function that checks for MKI. + * + * The function call srtp_unprotect(ctx, srtp_hdr, len_ptr) verifies + * the Secure RTP protection of the SRTP packet pointed to by srtp_hdr + * (which has length *len_ptr), using the SRTP context ctx. If + * srtp_err_status_ok is returned, then srtp_hdr points to the resulting + * RTP packet and *len_ptr is the number of octets in that packet; + * otherwise, no assumptions should be made about the value of either + * data elements. + * + * The sequence numbers of the RTP packets presented to this function + * need not be consecutive, but they @b must be out of order by less + * than 2^15 = 32,768 packets. + * + * @warning This function assumes that the SRTP packet is aligned on a + * 32-bit boundary. + * + * @param ctx is the SRTP session which applies to the particular packet. + * + * @param srtp_hdr is a pointer to the header of the SRTP packet + * (before the call). after the function returns, it points to the + * rtp packet if srtp_err_status_ok was returned; otherwise, the value of + * the data to which it points is undefined. + * + * @param len_ptr is a pointer to the length in octets of the complete + * srtp packet (header and body) before the function call, and of the + * complete rtp packet after the call, if srtp_err_status_ok was returned. + * Otherwise, the value of the data to which it points is undefined. + * + * @return + * - srtp_err_status_ok if the RTP packet is valid. + * - srtp_err_status_auth_fail if the SRTP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTP packet is a replay (e.g. packet has + * already been processed and accepted). + * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI id + * - [other] if there has been an error in the cryptographic mechanisms. + * + */ + + srtp_err_status_t srtp_unprotect_mki(srtp_t ctx, void *srtp_hdr, int *len_ptr, unsigned int use_mki); /** * @brief srtp_create() allocates and initializes an SRTP session. @@ -1261,6 +1375,55 @@ srtp_append_salt_to_key(unsigned char *key, unsigned int bytes_in_key, srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len); + +/** + * @brief srtp_protect_rtcp_mki() is the Secure RTCP sender-side packet + * processing function that can utilize mki. + * + * The function call srtp_protect_rtcp(ctx, rtp_hdr, len_ptr) applies + * SRTCP protection to the RTCP packet rtcp_hdr (which has length + * *len_ptr) using the SRTP session context ctx. If srtp_err_status_ok is + * returned, then rtp_hdr points to the resulting SRTCP packet and + * *len_ptr is the number of octets in that packet; otherwise, no + * assumptions should be made about the value of either data elements. + * + * @warning This function assumes that it can write the authentication + * tag into the location in memory immediately following the RTCP + * packet, and assumes that the RTCP packet is aligned on a 32-bit + * boundary. + * + * @warning This function assumes that it can write SRTP_MAX_TRAILER_LEN+4 + * into the location in memory immediately following the RTCP packet. + * Callers MUST ensure that this much writable memory is available in + * the buffer that holds the RTCP packet. + * + * @param ctx is the SRTP context to use in processing the packet. + * + * @param rtcp_hdr is a pointer to the RTCP packet (before the call); after + * the function returns, it points to the srtp packet. + * + * @param pkt_octet_len is a pointer to the length in octets of the + * complete RTCP packet (header and body) before the function call, + * and of the complete SRTCP packet after the call, if srtp_err_status_ok + * was returned. Otherwise, the value of the data to which it points + * is undefined. + * + * @param use_mki is a boolean to tell the system if mki is being used. If + * set to false then will use the first set of session keys. If set to true will + * use the session keys identified by the mki_index + * + * @param mki_index integer value specifying which set of session kesy should be + * used if use_mki is set to true. + * + * @return + * - srtp_err_status_ok if there were no problems. + * - [other] if there was a failure in + * the cryptographic mechanisms. + */ + +srtp_err_status_t srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, + unsigned int use_mki, unsigned int mki_index); + /** * @brief srtp_unprotect_rtcp() is the Secure RTCP receiver-side packet * processing function. @@ -1302,6 +1465,49 @@ srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_l srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len); +/** + * @brief srtp_unprotect_rtcp() is the Secure RTCP receiver-side packet + * processing function. + * + * The function call srtp_unprotect_rtcp(ctx, srtp_hdr, len_ptr) + * verifies the Secure RTCP protection of the SRTCP packet pointed to + * by srtcp_hdr (which has length *len_ptr), using the SRTP session + * context ctx. If srtp_err_status_ok is returned, then srtcp_hdr points + * to the resulting RTCP packet and *len_ptr is the number of octets + * in that packet; otherwise, no assumptions should be made about the + * value of either data elements. + * + * @warning This function assumes that the SRTCP packet is aligned on a + * 32-bit boundary. + * + * @param ctx is a pointer to the srtp_t which applies to the + * particular packet. + * + * @param srtcp_hdr is a pointer to the header of the SRTCP packet + * (before the call). After the function returns, it points to the + * rtp packet if srtp_err_status_ok was returned; otherwise, the value of + * the data to which it points is undefined. + * + * @param pkt_octet_len is a pointer to the length in octets of the + * complete SRTCP packet (header and body) before the function call, + * and of the complete rtp packet after the call, if srtp_err_status_ok was + * returned. Otherwise, the value of the data to which it points is + * undefined. + * + * @return + * - srtp_err_status_ok if the RTCP packet is valid. + * - srtp_err_status_auth_fail if the SRTCP packet failed the message + * authentication check. + * - srtp_err_status_replay_fail if the SRTCP packet is a replay (e.g. has + * already been processed and accepted). + * - srtp_err_status_bad_mki if the MKI in the packet is not a known MKI id + * - [other] if there has been an error in the cryptographic mechanisms. + * + */ + +srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigned int use_mki); + + /** * @} */ @@ -1484,6 +1690,18 @@ srtp_err_status_t srtp_set_debug_module(char *mod_name, int v); */ srtp_err_status_t srtp_list_debug_modules(void); +/** + * @brief srtp_get_protect_data_added_length(policy, use_mki, mki_index, is_rtcp, length) + * + * Determines the length of the amount of data Lib SRTP will add to the + * packet during the protect process. The length is returned in the length parameter + * + * returns err_status_ok on success, err_status_bad_mki if the MKI index is invalid + * + */ +srtp_err_status_t srtp_get_protect_data_added_length(const srtp_policy_t *policy, uint32_t use_mki, + uint32_t mki_index, uint32_t is_rtcp, uint32_t *length); + /** * @} diff --git a/include/srtp_priv.h b/include/srtp_priv.h index 4952d7907..51e1babb1 100644 --- a/include/srtp_priv.h +++ b/include/srtp_priv.h @@ -78,7 +78,15 @@ srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc); * srtp_stream_init_keys(s, k) (re)initializes the srtp_stream_t s by * deriving all of the needed keys using the KDF and the key k. */ -srtp_err_status_t srtp_stream_init_keys(srtp_stream_t srtp, const void *key); +srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t master_key, const unsigned int current_mki_index); + + +/* + * srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s by + * deriving all of the needed keys for all the master keys using the KDF and the keys from k. + */ +srtp_err_status_t srtp_steam_init_all_master_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t keys[SRTP_MAX_NUM_MASTER_KEYS], + const unsigned int max_master_keys); /* * srtp_stream_init(s, p) initializes the srtp_stream_t s to @@ -97,6 +105,24 @@ typedef enum direction_t { dir_srtp_receiver = 2 } direction_t; +/* + * srtp_session_keys_t will contain the encryption, hmac, salt keys + * for both SRTP and SRTCP. The session keys will also contain the + * MKI ID which is used to identify the session keys. + */ +typedef struct srtp_session_keys_t { + srtp_cipher_t *rtp_cipher; + srtp_cipher_t *rtp_xtn_hdr_cipher; + srtp_auth_t *rtp_auth; + srtp_cipher_t *rtcp_cipher; + srtp_auth_t *rtcp_auth; + uint8_t salt[SRTP_AEAD_SALT_LEN]; + uint8_t c_salt[SRTP_AEAD_SALT_LEN]; + uint8_t *mki_id; + unsigned int mki_size; +} srtp_session_keys_t; + + /* * an srtp_stream_t has its own SSRC, encryption key, authentication * key, sequence number, and replay database @@ -107,21 +133,16 @@ typedef enum direction_t { typedef struct srtp_stream_ctx_t_ { uint32_t ssrc; - srtp_cipher_t *rtp_cipher; - srtp_cipher_t *rtp_xtn_hdr_cipher; - srtp_auth_t *rtp_auth; + srtp_session_keys_t session_keys[SRTP_MAX_NUM_MASTER_KEYS]; + unsigned int num_master_keys; srtp_rdbx_t rtp_rdbx; srtp_sec_serv_t rtp_services; - srtp_cipher_t *rtcp_cipher; - srtp_auth_t *rtcp_auth; srtp_rdb_t rtcp_rdb; srtp_sec_serv_t rtcp_services; srtp_key_limit_ctx_t *limit; direction_t direction; int allow_repeat_tx; srtp_ekt_stream_t ekt; - uint8_t salt[SRTP_AEAD_SALT_LEN]; /* used with GCM mode for SRTP */ - uint8_t c_salt[SRTP_AEAD_SALT_LEN]; /* used with GCM mode for SRTCP */ int *enc_xtn_hdr; int enc_xtn_hdr_count; struct srtp_stream_ctx_t_ *next; /* linked list of streams */ diff --git a/srtp/srtp.c b/srtp/srtp.c index 065b3fb38..27f164c6e 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -147,27 +147,44 @@ unsigned int srtp_get_version () /* Release (maybe partially allocated) stream. */ static void srtp_stream_free(srtp_stream_ctx_t *str) { - if (str->rtp_xtn_hdr_cipher) { - srtp_cipher_dealloc(str->rtp_xtn_hdr_cipher); + unsigned int i = 0; + srtp_session_keys_t *session_keys = NULL; + + for (i = 0; i < str->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + + if (session_keys->rtp_xtn_hdr_cipher) { + srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); + } + + if (session_keys->rtcp_cipher) { + srtp_cipher_dealloc(session_keys->rtcp_cipher); + } + + if (session_keys->rtcp_auth) { + srtp_auth_dealloc(session_keys->rtcp_auth); + } + + if (session_keys->rtp_cipher) { + srtp_cipher_dealloc(session_keys->rtp_cipher); + } + + if (session_keys->rtp_auth) { + srtp_auth_dealloc(session_keys->rtp_auth); + } + + if (session_keys->mki_id) { + srtp_crypto_free(session_keys->mki_id); + } } + if (str->enc_xtn_hdr) { srtp_crypto_free(str->enc_xtn_hdr); } - if (str->rtcp_auth) { - srtp_auth_dealloc(str->rtcp_auth); - } - if (str->rtcp_cipher) { - srtp_cipher_dealloc(str->rtcp_cipher); - } if (str->limit) { srtp_crypto_free(str->limit); } - if (str->rtp_auth) { - srtp_auth_dealloc(str->rtp_auth); - } - if (str->rtp_cipher) { - srtp_cipher_dealloc(str->rtp_cipher); - } + srtp_crypto_free(str); } @@ -176,6 +193,8 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, const srtp_policy_t *p) { srtp_stream_ctx_t *str; srtp_err_status_t stat; + unsigned int i = 0; + srtp_session_keys_t *session_keys = NULL; /* * This function allocates the stream context, rtp and rtcp ciphers @@ -193,56 +212,65 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, memset(str, 0, sizeof(srtp_stream_ctx_t)); *str_ptr = str; - /* allocate cipher */ - stat = srtp_crypto_kernel_alloc_cipher(p->rtp.cipher_type, - &str->rtp_cipher, - p->rtp.cipher_key_len, - p->rtp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; - } + str->num_master_keys = p->num_master_keys; + + for (i = 0; i < str->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + + /* allocate cipher */ + stat = srtp_crypto_kernel_alloc_cipher(p->rtp.cipher_type, + &session_keys->rtp_cipher, + p->rtp.cipher_key_len, + p->rtp.auth_tag_len); + if (stat) { + srtp_stream_free(str); + return stat; + } + + /* allocate auth function */ + stat = srtp_crypto_kernel_alloc_auth(p->rtp.auth_type, + &session_keys->rtp_auth, + p->rtp.auth_key_len, + p->rtp.auth_tag_len); + if (stat) { + srtp_stream_free(str); + return stat; + } + + /* + * ...and now the RTCP-specific initialization - first, allocate + * the cipher + */ + stat = srtp_crypto_kernel_alloc_cipher(p->rtcp.cipher_type, + &session_keys->rtcp_cipher, + p->rtcp.cipher_key_len, + p->rtcp.auth_tag_len); + if (stat) { + srtp_stream_free(str); + return stat; + } + + /* allocate auth function */ + stat = srtp_crypto_kernel_alloc_auth(p->rtcp.auth_type, + &session_keys->rtcp_auth, + p->rtcp.auth_key_len, + p->rtcp.auth_tag_len); + if (stat) { + srtp_stream_free(str); + return stat; + } + + session_keys->mki_id = NULL; - /* allocate auth function */ - stat = srtp_crypto_kernel_alloc_auth(p->rtp.auth_type, - &str->rtp_auth, - p->rtp.auth_key_len, - p->rtp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; } - + /* allocate key limit structure */ str->limit = (srtp_key_limit_ctx_t*) srtp_crypto_alloc(sizeof(srtp_key_limit_ctx_t)); if (str->limit == NULL) { - srtp_stream_free(str); - return srtp_err_status_alloc_fail; - } - - /* - * ...and now the RTCP-specific initialization - first, allocate - * the cipher - */ - stat = srtp_crypto_kernel_alloc_cipher(p->rtcp.cipher_type, - &str->rtcp_cipher, - p->rtcp.cipher_key_len, - p->rtcp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; + srtp_stream_free(str); + return srtp_err_status_alloc_fail; } - /* allocate auth function */ - stat = srtp_crypto_kernel_alloc_auth(p->rtcp.auth_type, - &str->rtcp_auth, - p->rtcp.auth_key_len, - p->rtcp.auth_tag_len); - if (stat) { - srtp_stream_free(str); - return stat; - } - /* allocate ekt data associated with stream */ stat = srtp_ekt_alloc(&str->ekt, p->ekt); if (stat) { @@ -278,17 +306,25 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, break; } - /* allocate cipher for extensions header encryption */ - stat = srtp_crypto_kernel_alloc_cipher(enc_xtn_hdr_cipher_type, - &str->rtp_xtn_hdr_cipher, - enc_xtn_hdr_cipher_key_len, - 0); - if (stat) { - srtp_stream_free(str); - return stat; + for (i = 0; i < str->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + + /* allocate cipher for extensions header encryption */ + stat = srtp_crypto_kernel_alloc_cipher(enc_xtn_hdr_cipher_type, + &session_keys->rtp_xtn_hdr_cipher, + enc_xtn_hdr_cipher_key_len, + 0); + if (stat) { + srtp_stream_free(str); + return stat; + } } } else { - str->rtp_xtn_hdr_cipher = NULL; + for (i = 0; i < str->num_master_keys; i++) { + session_keys = &str->session_keys[i]; + session_keys->rtp_xtn_hdr_cipher = NULL; + } + str->enc_xtn_hdr = NULL; str->enc_xtn_hdr_count = 0; } @@ -299,74 +335,99 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, 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]; - /* deallocate cipher, if it is not the same as that in template */ - if (stream_template - && stream->rtp_cipher == stream_template->rtp_cipher) { - /* do nothing */ - } else { - status = srtp_cipher_dealloc(stream->rtp_cipher); - if (status) - return status; - } + if (stream_template) { + template_session_keys = &stream_template->session_keys[i]; + } else { + template_session_keys = NULL; + } - /* deallocate auth function, if it is not the same as that in template */ - if (stream_template - && stream->rtp_auth == stream_template->rtp_auth) { - /* do nothing */ - } else { - status = srtp_auth_dealloc(stream->rtp_auth); - if (status) - return status; - } + /* 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 key usage limit, if it is not the same as that in template */ - if (stream_template - && stream->limit == stream_template->limit) { - /* do nothing */ - } else { - srtp_crypto_free(stream->limit); - } + /* 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 (stream_template - && stream->rtp_xtn_hdr_cipher == stream_template->rtp_xtn_hdr_cipher) { - /* do nothing */ - } else if (stream->rtp_xtn_hdr_cipher) { - status = srtp_cipher_dealloc(stream->rtp_xtn_hdr_cipher); - 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 + */ + memset(session_keys->salt, 0, SRTP_AEAD_SALT_LEN); + memset(session_keys->c_salt, 0, SRTP_AEAD_SALT_LEN); + + if (session_keys->mki_id) { + memset(session_keys->mki_id, 0, session_keys->mki_size); + srtp_crypto_free(session_keys->mki_id); + session_keys->mki_id = NULL; + } - /* - * deallocate rtcp cipher, if it is not the same as that in - * template - */ - if (stream_template - && stream->rtcp_cipher == stream_template->rtcp_cipher) { - /* do nothing */ - } else { - status = srtp_cipher_dealloc(stream->rtcp_cipher); - if (status) - return status; } - /* - * deallocate rtcp auth function, if it is not the same as that in - * template - */ + /* deallocate key usage limit, if it is not the same as that in template */ if (stream_template - && stream->rtcp_auth == stream_template->rtcp_auth) { - /* do nothing */ + && stream->limit == stream_template->limit) { + /* do nothing */ } else { - status = srtp_auth_dealloc(stream->rtcp_auth); - if (status) - return status; + srtp_crypto_free(stream->limit); } status = srtp_rdbx_dealloc(&stream->rtp_rdbx); @@ -382,13 +443,6 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat srtp_crypto_free(stream->enc_xtn_hdr); } - /* - * zeroize the salt value - */ - memset(stream->salt, 0, SRTP_AEAD_SALT_LEN); - memset(stream->c_salt, 0, SRTP_AEAD_SALT_LEN); - - /* deallocate srtp stream context */ srtp_crypto_free(stream); @@ -410,6 +464,9 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, srtp_stream_ctx_t **str_ptr) { srtp_err_status_t status; srtp_stream_ctx_t *str; + unsigned int i = 0; + srtp_session_keys_t *session_keys = NULL; + const srtp_session_keys_t *template_session_keys = NULL; debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ntohl(ssrc)); @@ -419,12 +476,33 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, return srtp_err_status_alloc_fail; *str_ptr = str; - /* set cipher and auth pointers to those of the template */ - str->rtp_cipher = stream_template->rtp_cipher; - str->rtp_auth = stream_template->rtp_auth; - str->rtp_xtn_hdr_cipher = stream_template->rtp_xtn_hdr_cipher; - str->rtcp_cipher = stream_template->rtcp_cipher; - str->rtcp_auth = stream_template->rtcp_auth; + str->num_master_keys = stream_template->num_master_keys; + + for (i = 0; i < stream_template->num_master_keys; i++){ + session_keys = &str->session_keys[i]; + template_session_keys = &stream_template->session_keys[i]; + + /* set cipher and auth pointers to those of the template */ + session_keys->rtp_cipher = template_session_keys->rtp_cipher; + session_keys->rtp_auth = template_session_keys->rtp_auth; + session_keys->rtp_xtn_hdr_cipher = template_session_keys->rtp_xtn_hdr_cipher; + session_keys->rtcp_cipher = template_session_keys->rtcp_cipher; + session_keys->rtcp_auth = template_session_keys->rtcp_auth; + session_keys->mki_size = template_session_keys->mki_size; + + session_keys->mki_id = srtp_crypto_alloc(template_session_keys->mki_size); + + if (session_keys->mki_id == NULL) { + return srtp_err_status_init_fail; + } + + memset(session_keys->mki_id, 0x0, session_keys->mki_size); + memcpy(session_keys->mki_id, template_session_keys->mki_id, session_keys->mki_size); + + /* Copy the salt values */ + memcpy(session_keys->salt, template_session_keys->salt, SRTP_AEAD_SALT_LEN); + memcpy(session_keys->c_salt, template_session_keys->c_salt, SRTP_AEAD_SALT_LEN); + } /* set key limit to point to that of the template */ status = srtp_key_limit_clone(stream_template->limit, &str->limit); @@ -456,10 +534,6 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, /* set pointer to EKT data associated with stream */ str->ekt = stream_template->ekt; - /* Copy the salt values */ - memcpy(str->salt, stream_template->salt, SRTP_AEAD_SALT_LEN); - memcpy(str->c_salt, stream_template->c_salt, SRTP_AEAD_SALT_LEN); - /* copy information about extensions header encryption */ str->enc_xtn_hdr = stream_template->enc_xtn_hdr; str->enc_xtn_hdr_count = stream_template->enc_xtn_hdr_count; @@ -660,21 +734,100 @@ static inline int base_key_length(const srtp_cipher_type_t *cipher, int key_leng } } +unsigned int +srtp_validate_policy_master_keys(const srtp_policy_t *policy) +{ + int i = 0; + + if (policy->num_master_keys <= 0) + return 0; + + for (i = 0; i < policy->num_master_keys; i++) { + if (policy->keys[i].key == NULL) + return 0; + } + + return 1; +} + +srtp_session_keys_t* +srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t *stream, unsigned int use_mki, unsigned int mki_index) +{ + if (use_mki) { + if (mki_index < stream->num_master_keys) { + return &stream->session_keys[mki_index]; + } + } + return &stream->session_keys[0]; +} + +unsigned int +srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, unsigned int use_mki) +{ + unsigned int mki_size = 0; + + if (use_mki) { + mki_size = session_keys->mki_size; + + if (mki_size != 0) { + // Write MKI into memory + memcpy(mki_tag_location, session_keys->mki_id, mki_size); + } + } + + return mki_size; +} + +srtp_err_status_t +srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t keys[SRTP_MAX_NUM_MASTER_KEYS], + const unsigned int max_master_keys) { + int i = 0; + srtp_err_status_t status = srtp_err_status_ok; + + srtp->num_master_keys = max_master_keys; + + for (i = 0; i < srtp->num_master_keys && i < SRTP_MAX_NUM_MASTER_KEYS; i++) { + status = srtp_stream_init_keys(srtp, keys[i], i); + + if (status) { + return status; + } + } + + return status; +} + srtp_err_status_t -srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { +srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t master_key, const unsigned int current_mki_index) { srtp_err_status_t stat; srtp_kdf_t kdf; uint8_t tmp_key[MAX_SRTP_KEY_LEN]; int kdf_keylen = 30, rtp_keylen, rtcp_keylen; int rtp_base_key_len, rtp_salt_len; int rtcp_base_key_len, rtcp_salt_len; + srtp_session_keys_t *session_keys = NULL; + unsigned char *key = master_key.key; /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */ /* TODO: kdf algorithm, master key length, and master salt length should * be part of srtp_policy_t. */ - rtp_keylen = srtp_cipher_get_key_length(srtp->rtp_cipher); - rtcp_keylen = srtp_cipher_get_key_length(srtp->rtcp_cipher); - rtp_base_key_len = base_key_length(srtp->rtp_cipher->type, rtp_keylen); + + session_keys = &srtp->session_keys[current_mki_index]; + + session_keys->mki_id = srtp_crypto_alloc(master_key.mki_size); + + if (session_keys->mki_id == NULL) { + return srtp_err_status_init_fail; + } + + memset(session_keys->mki_id, 0x0, master_key.mki_size); + memcpy(session_keys->mki_id, master_key.mki_id, master_key.mki_size); + + session_keys->mki_size = master_key.mki_size; + + rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher); + rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher); + rtp_base_key_len = base_key_length(session_keys->rtp_cipher->type, rtp_keylen); rtp_salt_len = rtp_keylen - rtp_base_key_len; if (rtp_keylen > kdf_keylen) { @@ -735,7 +888,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); return srtp_err_status_init_fail; } - memcpy(srtp->salt, tmp_key + rtp_base_key_len, SRTP_AEAD_SALT_LEN); + memcpy(session_keys->salt, tmp_key + rtp_base_key_len, SRTP_AEAD_SALT_LEN); } if (rtp_salt_len > 0) { debug_print(mod_srtp, "cipher salt: %s", @@ -743,14 +896,14 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { } /* initialize cipher */ - stat = srtp_cipher_init(srtp->rtp_cipher, tmp_key); + stat = srtp_cipher_init(session_keys->rtp_cipher, tmp_key); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); return srtp_err_status_init_fail; } - if (srtp->rtp_xtn_hdr_cipher) { + if (session_keys->rtp_xtn_hdr_cipher) { /* generate extensions header encryption key */ int rtp_xtn_hdr_keylen; int rtp_xtn_hdr_base_key_len; @@ -758,12 +911,12 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { srtp_kdf_t tmp_kdf; srtp_kdf_t *xtn_hdr_kdf; - if (srtp->rtp_xtn_hdr_cipher->type != srtp->rtp_cipher->type) { + if (session_keys->rtp_xtn_hdr_cipher->type != session_keys->rtp_cipher->type) { /* With GCM ciphers, the header extensions are still encrypted using the corresponding ICM cipher. */ /* See https://tools.ietf.org/html/draft-ietf-avtcore-srtp-aes-gcm-17#section-8.3 */ uint8_t tmp_xtn_hdr_key[MAX_SRTP_KEY_LEN]; - rtp_xtn_hdr_keylen = srtp_cipher_get_key_length(srtp->rtp_xtn_hdr_cipher); - rtp_xtn_hdr_base_key_len = base_key_length(srtp->rtp_xtn_hdr_cipher->type, rtp_xtn_hdr_keylen); + rtp_xtn_hdr_keylen = srtp_cipher_get_key_length(session_keys->rtp_xtn_hdr_cipher); + rtp_xtn_hdr_base_key_len = base_key_length(session_keys->rtp_xtn_hdr_cipher->type, rtp_xtn_hdr_keylen); rtp_xtn_hdr_salt_len = rtp_xtn_hdr_keylen - rtp_xtn_hdr_base_key_len; memset(tmp_xtn_hdr_key, 0x0, MAX_SRTP_KEY_LEN); memcpy(tmp_xtn_hdr_key, key, (rtp_xtn_hdr_base_key_len + rtp_xtn_hdr_salt_len)); @@ -819,7 +972,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { } /* initialize extensions header cipher */ - stat = srtp_cipher_init(srtp->rtp_xtn_hdr_cipher, tmp_key); + stat = srtp_cipher_init(session_keys->rtp_xtn_hdr_cipher, tmp_key); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); @@ -838,7 +991,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { /* generate authentication key */ stat = srtp_kdf_generate(&kdf, label_rtp_msg_auth, - tmp_key, srtp_auth_get_key_length(srtp->rtp_auth)); + tmp_key, srtp_auth_get_key_length(session_keys->rtp_auth)); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); @@ -846,10 +999,10 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { } debug_print(mod_srtp, "auth key: %s", srtp_octet_string_hex_string(tmp_key, - srtp_auth_get_key_length(srtp->rtp_auth))); + srtp_auth_get_key_length(session_keys->rtp_auth))); /* initialize auth function */ - stat = srtp_auth_init(srtp->rtp_auth, tmp_key); + stat = srtp_auth_init(session_keys->rtp_auth, tmp_key); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); @@ -860,7 +1013,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { * ...now initialize SRTCP keys */ - rtcp_base_key_len = base_key_length(srtp->rtcp_cipher->type, rtcp_keylen); + rtcp_base_key_len = base_key_length(session_keys->rtcp_cipher->type, rtcp_keylen); rtcp_salt_len = rtcp_keylen - rtcp_base_key_len; debug_print(mod_srtp, "rtcp salt len: %d", rtcp_salt_len); @@ -889,7 +1042,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); return srtp_err_status_init_fail; } - memcpy(srtp->c_salt, tmp_key + rtcp_base_key_len, SRTP_AEAD_SALT_LEN); + memcpy(session_keys->c_salt, tmp_key + rtcp_base_key_len, SRTP_AEAD_SALT_LEN); } debug_print(mod_srtp, "rtcp cipher key: %s", srtp_octet_string_hex_string(tmp_key, rtcp_base_key_len)); @@ -899,7 +1052,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { } /* initialize cipher */ - stat = srtp_cipher_init(srtp->rtcp_cipher, tmp_key); + stat = srtp_cipher_init(session_keys->rtcp_cipher, tmp_key); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); @@ -908,7 +1061,7 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { /* generate authentication key */ stat = srtp_kdf_generate(&kdf, label_rtcp_msg_auth, - tmp_key, srtp_auth_get_key_length(srtp->rtcp_auth)); + tmp_key, srtp_auth_get_key_length(session_keys->rtcp_auth)); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); @@ -917,10 +1070,10 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) { debug_print(mod_srtp, "rtcp auth key: %s", srtp_octet_string_hex_string(tmp_key, - srtp_auth_get_key_length(srtp->rtcp_auth))); + srtp_auth_get_key_length(session_keys->rtcp_auth))); /* initialize auth function */ - stat = srtp_auth_init(srtp->rtcp_auth, tmp_key); + stat = srtp_auth_init(session_keys->rtcp_auth, tmp_key); if (stat) { /* zeroize temp buffer */ octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); @@ -997,7 +1150,7 @@ srtp_stream_init(srtp_stream_ctx_t *srtp, /* DAM - no RTCP key limit at present */ /* initialize keys */ - err = srtp_stream_init_keys(srtp, p->key); + err = srtp_stream_init_all_master_keys(srtp, p->keys, p->num_master_keys); if (err) { srtp_rdbx_dealloc(&srtp->rtp_rdbx); return err; @@ -1102,7 +1255,7 @@ srtp_protect_extension_header(srtp_stream_ctx_t *stream, int id) { * extensions header encryption RFC 6904 */ static srtp_err_status_t -srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_hdr) { +srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_hdr, srtp_session_keys_t *session_keys) { srtp_err_status_t status; uint8_t keystream[257]; /* Maximum 2 bytes header + 255 bytes data. */ int keystream_pos; @@ -1125,7 +1278,7 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_h break; } - status = srtp_cipher_output(stream->rtp_xtn_hdr_cipher, keystream, &xlen_with_header); + status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, keystream, &xlen_with_header); if (status) return srtp_err_status_cipher_fail; @@ -1156,7 +1309,7 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_h if (xtn_hdr_data + xlen > xtn_hdr_end) return srtp_err_status_parse_err; - status = srtp_cipher_output(stream->rtp_xtn_hdr_cipher, keystream, &xlen_with_header); + status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, keystream, &xlen_with_header); if (status) return srtp_err_status_cipher_fail; @@ -1205,15 +1358,16 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_h * | Initialization Vector |<--+ * +--+--+--+--+--+--+--+--+--+--+--+--+* * - * Input: *stream - pointer to SRTP stream context, used to retrieve - * the SALT + * Input: *session_keys - pointer to SRTP stream context session keys, + * used to retrieve the SALT * *iv - Pointer to receive the calculated IV * *seq - The ROC and SEQ value to use for the * IV calculation. * *hdr - The RTP header, used to get the SSRC value * */ -static void srtp_calc_aead_iv(srtp_stream_ctx_t *stream, v128_t *iv, + +static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys, v128_t *iv, srtp_xtd_seq_num_t *seq, srtp_hdr_t *hdr) { v128_t in; @@ -1244,7 +1398,7 @@ static void srtp_calc_aead_iv(srtp_stream_ctx_t *stream, v128_t *iv, /* * Get the SALT value from the context */ - memcpy(salt.v8, stream->salt, SRTP_AEAD_SALT_LEN); + memcpy(salt.v8, session_keys->salt, SRTP_AEAD_SALT_LEN); debug_print(mod_srtp, "RTP SALT = %s\n", v128_hex_string(&salt)); /* @@ -1254,6 +1408,38 @@ static void srtp_calc_aead_iv(srtp_stream_ctx_t *stream, v128_t *iv, } +srtp_session_keys_t* +srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, const unsigned int* pkt_octet_len, unsigned int* mki_size) { + + unsigned int base_mki_start_location = *pkt_octet_len; + unsigned int mki_start_location = 0; + unsigned int tag_len = 0; + unsigned int i = 0; + + // Determine the authentication tag size + if (stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_128_GCM || + stream->session_keys[0].rtp_cipher->algorithm == SRTP_AES_256_GCM) { + tag_len = 0; + } else { + tag_len = srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth); + } + + base_mki_start_location -= tag_len; + + for (i = 0; i < stream->num_master_keys; i++) { + *mki_size = stream->session_keys[i].mki_size; + mki_start_location = base_mki_start_location - *mki_size; + + if ( mki_start_location >= *mki_size && + memcmp(hdr + mki_start_location, stream->session_keys[i].mki_id, *mki_size) == 0 ) { + return &stream->session_keys[i]; + } + } + + *mki_size = 0; + return NULL; +} + /* * This function handles outgoing SRTP packets while in AEAD mode, * which currently supports AES-GCM encryption. All packets are @@ -1261,7 +1447,8 @@ static void srtp_calc_aead_iv(srtp_stream_ctx_t *stream, v128_t *iv, */ static srtp_err_status_t srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, - void *rtp_hdr, unsigned int *pkt_octet_len) + void *rtp_hdr, unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, unsigned int use_mki) { srtp_hdr_t *hdr = (srtp_hdr_t*)rtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ @@ -1273,6 +1460,8 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, v128_t iv; unsigned int aad_len; srtp_hdr_xtnd_t *xtn_hdr = NULL; + unsigned int mki_size = 0; + uint8_t *mki_location = NULL; debug_print(mod_srtp, "function srtp_protect_aead", NULL); @@ -1294,7 +1483,7 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, } /* get tag length from stream */ - tag_len = srtp_auth_get_tag_length(stream->rtp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); /* * find starting point for encryption and length of data to be @@ -1338,7 +1527,7 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, /* * AEAD uses a new IV formation method */ - srtp_calc_aead_iv(stream, &iv, &est, hdr); + srtp_calc_aead_iv(session_keys, &iv, &est, hdr); /* shift est, put into network byte order */ #ifdef NO_64BIT_MATH est = be64_to_cpu(make64((high32(est) << 16) | @@ -1348,22 +1537,22 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, est = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(stream->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - if (!status && stream->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { iv.v32[0] = 0; iv.v32[1] = hdr->ssrc; iv.v64[1] = est; - status = srtp_cipher_set_iv(stream->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); } if (status) { return srtp_err_status_cipher_fail; } - if (xtn_hdr && stream->rtp_xtn_hdr_cipher) { + if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* * extensions header encryption RFC 6904 */ - status = srtp_process_header_encryption(stream, xtn_hdr); + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status; } @@ -1373,13 +1562,13 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * Set the AAD over the RTP header */ aad_len = (uint8_t *)enc_start - (uint8_t *)hdr; - status = srtp_cipher_set_aad(stream->rtp_cipher, (uint8_t*)hdr, aad_len); + status = srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t*)hdr, aad_len); if (status) { return ( srtp_err_status_cipher_fail); } /* Encrypt the payload */ - status = srtp_cipher_encrypt(stream->rtp_cipher, + status = srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t*)enc_start, (unsigned int *)&enc_octet_len); if (status) { return srtp_err_status_cipher_fail; @@ -1388,15 +1577,21 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * If we're doing GCM, we need to get the tag * and append that to the output */ - status = srtp_cipher_get_tag(stream->rtp_cipher, + status = srtp_cipher_get_tag(session_keys->rtp_cipher, (uint8_t*)enc_start+enc_octet_len, &tag_len); if (status) { return ( srtp_err_status_cipher_fail); } + mki_location = (uint8_t *)hdr + *pkt_octet_len + tag_len; + mki_size = srtp_inject_mki(mki_location, session_keys, use_mki); + /* increase the packet length by the length of the auth tag */ *pkt_octet_len += tag_len; + /* increase the packet length by the length of the mki_size */ + *pkt_octet_len += mki_size; + return srtp_err_status_ok; } @@ -1410,7 +1605,8 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, */ static srtp_err_status_t srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, - srtp_xtd_seq_num_t est, void *srtp_hdr, unsigned int *pkt_octet_len) + srtp_xtd_seq_num_t est, void *srtp_hdr, unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, unsigned int mki_size) { srtp_hdr_t *hdr = (srtp_hdr_t*)srtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ @@ -1430,14 +1626,14 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, #endif /* get tag length from stream */ - tag_len = srtp_auth_get_tag_length(stream->rtp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); /* * AEAD uses a new IV formation method */ - srtp_calc_aead_iv(stream, &iv, &est, hdr); - status = srtp_cipher_set_iv(stream->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); - if (!status && stream->rtp_xtn_hdr_cipher) { + srtp_calc_aead_iv(session_keys, &iv, &est, hdr); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { iv.v32[0] = 0; iv.v32[1] = hdr->ssrc; #ifdef NO_64BIT_MATH @@ -1446,7 +1642,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, #else iv.v64[1] = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(stream->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); } if (status) { return srtp_err_status_cipher_fail; @@ -1463,12 +1659,12 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, xtn_hdr = (srtp_hdr_xtnd_t*)enc_start; enc_start += (ntohs(xtn_hdr->length) + 1); } - if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len))) + if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len - mki_size))) return srtp_err_status_parse_err; /* * We pass the tag down to the cipher when doing GCM mode */ - enc_octet_len = (unsigned int)(*pkt_octet_len - + enc_octet_len = (unsigned int)(*pkt_octet_len - mki_size - ((uint8_t*)enc_start - (uint8_t*)hdr)); /* @@ -1502,23 +1698,23 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * Set the AAD for AES-GCM, which is the RTP header */ aad_len = (uint8_t *)enc_start - (uint8_t *)hdr; - status = srtp_cipher_set_aad(stream->rtp_cipher, (uint8_t*)hdr, aad_len); + status = srtp_cipher_set_aad(session_keys->rtp_cipher, (uint8_t*)hdr, aad_len); if (status) { return ( srtp_err_status_cipher_fail); } /* Decrypt the ciphertext. This also checks the auth tag based * on the AAD we just specified above */ - status = srtp_cipher_decrypt(stream->rtp_cipher, (uint8_t*)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtp_cipher, (uint8_t*)enc_start, &enc_octet_len); if (status) { return status; } - if (xtn_hdr && stream->rtp_xtn_hdr_cipher) { + if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* * extensions header encryption RFC 6904 */ - status = srtp_process_header_encryption(stream, xtn_hdr); + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status; } @@ -1579,12 +1775,20 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, /* decrease the packet length by the length of the auth tag */ *pkt_octet_len -= tag_len; + /* decrease the packet length by the length of the mki_size */ + *pkt_octet_len -= mki_size; + return srtp_err_status_ok; } srtp_err_status_t srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) { + return srtp_protect_mki(ctx, rtp_hdr, pkt_octet_len, 0, 0); + } + + srtp_err_status_t + srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len, unsigned int use_mki, unsigned int mki_index ) { srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -1597,6 +1801,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, srtp_stream_ctx_t *stream; uint32_t prefix_len; srtp_hdr_xtnd_t *xtn_hdr = NULL; + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; + uint8_t* mki_location = NULL; debug_print(mod_srtp, "function srtp_protect", NULL); @@ -1658,13 +1865,15 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, } } + session_keys = srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index); + /* * Check if this is an AEAD stream (GCM mode). If so, then dispatch * the request to our AEAD handler. */ - if (stream->rtp_cipher->algorithm == SRTP_AES_128_GCM || - stream->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_protect_aead(ctx, stream, rtp_hdr, (unsigned int*)pkt_octet_len); + if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || + session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { + return srtp_protect_aead(ctx, stream, rtp_hdr, (unsigned int*)pkt_octet_len, session_keys, use_mki); } /* @@ -1686,7 +1895,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, } /* get tag length from stream */ - tag_len = srtp_auth_get_tag_length(stream->rtp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); /* * find starting point for encryption and length of data to be @@ -1712,6 +1921,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, enc_start = NULL; } + mki_location = (uint8_t *)hdr + *pkt_octet_len; + mki_size = srtp_inject_mki(mki_location, session_keys, use_mki); + /* * if we're providing authentication, set the auth_start and auth_tag * pointers to the proper locations; otherwise, set auth_start to NULL @@ -1719,7 +1931,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, */ if (stream->rtp_services & sec_serv_auth) { auth_start = (uint32_t *)hdr; - auth_tag = (uint8_t *)hdr + *pkt_octet_len; + auth_tag = (uint8_t *)hdr + *pkt_octet_len + mki_size; } else { auth_start = NULL; auth_tag = NULL; @@ -1748,8 +1960,8 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, /* * if we're using rindael counter mode, set nonce and seq */ - if (stream->rtp_cipher->type->id == SRTP_AES_ICM || - stream->rtp_cipher->type->id == SRTP_AES_256_ICM) { + if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM || + session_keys->rtp_cipher->type->id == SRTP_AES_256_ICM) { v128_t iv; iv.v32[0] = 0; @@ -1760,9 +1972,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, #else iv.v64[1] = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(stream->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - if (!status && stream->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(stream->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); } } else { v128_t iv; @@ -1775,9 +1987,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, iv.v64[0] = 0; #endif iv.v64[1] = be64_to_cpu(est); - status = srtp_cipher_set_iv(stream->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); - if (!status && stream->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(stream->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); } } if (status) @@ -1798,9 +2010,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, */ if (auth_start) { - prefix_len = srtp_auth_get_prefix_length(stream->rtp_auth); + prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); if (prefix_len) { - status = srtp_cipher_output(stream->rtp_cipher, auth_tag, &prefix_len); + status = srtp_cipher_output(session_keys->rtp_cipher, auth_tag, &prefix_len); if (status) return srtp_err_status_cipher_fail; debug_print(mod_srtp, "keystream prefix: %s", @@ -1808,11 +2020,11 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, } } - if (xtn_hdr && stream->rtp_xtn_hdr_cipher) { + if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* * extensions header encryption RFC 6904 */ - status = srtp_process_header_encryption(stream, xtn_hdr); + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status; } @@ -1820,7 +2032,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, /* if we're encrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_encrypt(stream->rtp_cipher, + status = srtp_cipher_encrypt(session_keys->rtp_cipher, (uint8_t *)enc_start, (unsigned int *)&enc_octet_len); if (status) return srtp_err_status_cipher_fail; @@ -1833,17 +2045,17 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, if (auth_start) { /* initialize auth func context */ - status = srtp_auth_start(stream->rtp_auth); + status = srtp_auth_start(session_keys->rtp_auth); if (status) return status; /* run auth func over packet */ - status = srtp_auth_update(stream->rtp_auth, + status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start, *pkt_octet_len); if (status) return status; /* run auth func over ROC, put result into auth_tag */ debug_print(mod_srtp, "estimated packet index: %016llx", est); - status = srtp_auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, auth_tag); + status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, auth_tag); debug_print(mod_srtp, "srtp auth tag: %s", srtp_octet_string_hex_string(auth_tag, tag_len)); if (status) @@ -1857,12 +2069,22 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, *pkt_octet_len += tag_len; } + if (use_mki) { + /* increate the packet length by the mki size */ + *pkt_octet_len += mki_size; + } + return srtp_err_status_ok; } srtp_err_status_t srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { + return srtp_unprotect_mki(ctx, srtp_hdr, pkt_octet_len, 0); +} + +srtp_err_status_t +srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned int use_mki) { srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -1876,6 +2098,8 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { uint8_t tmp_tag[SRTP_MAX_TAG_LEN]; uint32_t tag_len, prefix_len; srtp_hdr_xtnd_t *xtn_hdr = NULL; + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; debug_print(mod_srtp, "function srtp_unprotect", NULL); @@ -1940,24 +2164,36 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { debug_print(mod_srtp, "estimated u_packet index: %016llx", est); #endif + /* + * Determine if MKI is being used and what the MKI index is + */ + if (use_mki) { + session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, (const unsigned int*)pkt_octet_len, &mki_size); + + if (session_keys == NULL) + return srtp_err_status_bad_mki; + } else { + session_keys = &stream->session_keys[0]; + } + /* * Check if this is an AEAD stream (GCM mode). If so, then dispatch * the request to our AEAD handler. */ - if (stream->rtp_cipher->algorithm == SRTP_AES_128_GCM || - stream->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, (unsigned int*)pkt_octet_len); + if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || + session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { + return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, (unsigned int*)pkt_octet_len, session_keys, mki_size); } /* get tag length from stream */ - tag_len = srtp_auth_get_tag_length(stream->rtp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtp_auth); /* * set the cipher's IV properly, depending on whatever cipher we * happen to be using */ - if (stream->rtp_cipher->type->id == SRTP_AES_ICM || - stream->rtp_cipher->type->id == SRTP_AES_256_ICM) { + if (session_keys->rtp_cipher->type->id == SRTP_AES_ICM || + session_keys->rtp_cipher->type->id == SRTP_AES_256_ICM) { /* aes counter mode */ iv.v32[0] = 0; @@ -1968,9 +2204,9 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { #else iv.v64[1] = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(stream->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); - if (!status && stream->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(stream->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_decrypt); } } else { @@ -1982,9 +2218,9 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { iv.v64[0] = 0; #endif iv.v64[1] = be64_to_cpu(est); - status = srtp_cipher_set_iv(stream->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); - if (!status && stream->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(stream->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + if (!status && session_keys->rtp_xtn_hdr_cipher) { + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_decrypt); } } if (status) @@ -2013,9 +2249,9 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { xtn_hdr = (srtp_hdr_xtnd_t *)enc_start; enc_start += (ntohs(xtn_hdr->length) + 1); } - if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len))) + if (!((uint8_t*)enc_start <= (uint8_t*)hdr + (*pkt_octet_len - tag_len - mki_size))) return srtp_err_status_parse_err; - enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - + enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len - mki_size - ((uint8_t*)enc_start - (uint8_t*)hdr)); } else { enc_start = NULL; @@ -2047,10 +2283,10 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { * if the keystream prefix length is zero, then we know that * the authenticator isn't using a universal hash function */ - if (stream->rtp_auth->prefix_len != 0) { + if (session_keys->rtp_auth->prefix_len != 0) { - prefix_len = srtp_auth_get_prefix_length(stream->rtp_auth); - status = srtp_cipher_output(stream->rtp_cipher, tmp_tag, &prefix_len); + prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); + status = srtp_cipher_output(session_keys->rtp_cipher, tmp_tag, &prefix_len); debug_print(mod_srtp, "keystream prefix: %s", srtp_octet_string_hex_string(tmp_tag, prefix_len)); if (status) @@ -2058,15 +2294,15 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { } /* initialize auth func context */ - status = srtp_auth_start(stream->rtp_auth); + status = srtp_auth_start(session_keys->rtp_auth); if (status) return status; /* now compute auth function over packet */ - status = srtp_auth_update(stream->rtp_auth, (uint8_t *)auth_start, - *pkt_octet_len - tag_len); + status = srtp_auth_update(session_keys->rtp_auth, (uint8_t *)auth_start, + *pkt_octet_len - tag_len - mki_size); /* run auth func over ROC, then write tmp tag */ - status = srtp_auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag); + status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4, tmp_tag); debug_print(mod_srtp, "computed auth tag: %s", srtp_octet_string_hex_string(tmp_tag, tag_len)); @@ -2097,11 +2333,11 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { break; } - if (xtn_hdr && stream->rtp_xtn_hdr_cipher) { + if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* * extensions header encryption RFC 6904 */ - status = srtp_process_header_encryption(stream, xtn_hdr); + status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status; } @@ -2109,7 +2345,7 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { /* if we're decrypting, add keystream into ciphertext */ if (enc_start) { - status = srtp_cipher_decrypt(stream->rtp_cipher, (uint8_t *)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtp_cipher, (uint8_t *)enc_start, &enc_octet_len); if (status) return srtp_err_status_cipher_fail; } @@ -2168,6 +2404,9 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { /* decrease the packet length by the length of the auth tag */ *pkt_octet_len -= tag_len; + /* decrease the packet length by the mki size */ + *pkt_octet_len -= mki_size; + return srtp_err_status_ok; } @@ -2287,7 +2526,7 @@ srtp_add_stream(srtp_t session, srtp_stream_t tmp; /* sanity check arguments */ - if ((session == NULL) || (policy == NULL) || (policy->key == NULL)) + if ((session == NULL) || (policy == NULL) || (!srtp_validate_policy_master_keys(policy))) return srtp_err_status_bad_param; /* allocate stream */ @@ -2420,7 +2659,7 @@ srtp_update(srtp_t session, const srtp_policy_t *policy) { srtp_err_status_t stat; /* sanity check arguments */ - if ((session == NULL) || (policy == NULL) || (policy->key == NULL)) { + if ((session == NULL) || (policy == NULL) || (!srtp_validate_policy_master_keys(policy))) { return srtp_err_status_bad_param; } @@ -2468,7 +2707,7 @@ update_template_streams(srtp_t session, const srtp_policy_t *policy) { srtp_rdb_t old_rtcp_rdb; stream = session->stream_list; - while ((stream != NULL) && (stream->rtp_auth != session->stream_template->rtp_auth)) { + while ((stream != NULL) && (stream->session_keys[0].rtp_auth != session->stream_template->session_keys[0].rtp_auth)) { stream = stream->next; } if (stream == NULL) { @@ -2576,7 +2815,7 @@ srtp_update_stream(srtp_t session, const srtp_policy_t *policy) { srtp_err_status_t status; /* sanity check arguments */ - if ((session == NULL) || (policy == NULL) || (policy->key == NULL)) + if ((session == NULL) || (policy == NULL) || (!srtp_validate_policy_master_keys(policy))) return srtp_err_status_bad_param; switch (policy->ssrc.type) { @@ -2855,14 +3094,14 @@ srtp_crypto_policy_set_aes_gcm_256_16_auth(srtp_crypto_policy_t *p) { * | Initialization Vector |<--+ * +--+--+--+--+--+--+--+--+--+--+--+--+* * - * Input: *stream - pointer to SRTP stream context, used to retrieve - * the SALT - * *iv - Pointer to recieve the calculated IV - * seq_num - The SEQ value to use for the IV calculation. - * *hdr - The RTP header, used to get the SSRC value + * Input: *session_keys - pointer to SRTP stream context session keys, + * used to retrieve the SALT + * *iv - Pointer to recieve the calculated IV + * seq_num - The SEQ value to use for the IV calculation. + * *hdr - The RTP header, used to get the SSRC value * */ -static void srtp_calc_aead_iv_srtcp(srtp_stream_ctx_t *stream, v128_t *iv, +static void srtp_calc_aead_iv_srtcp(srtp_session_keys_t *session_keys, v128_t *iv, uint32_t seq_num, srtcp_hdr_t *hdr) { v128_t in; @@ -2881,7 +3120,7 @@ static void srtp_calc_aead_iv_srtcp(srtp_stream_ctx_t *stream, v128_t *iv, /* * Get the SALT value from the context */ - memcpy(salt.v8, stream->c_salt, 12); + memcpy(salt.v8, session_keys->c_salt, 12); debug_print(mod_srtp, "RTCP SALT = %s\n", v128_hex_string(&salt)); /* @@ -2896,7 +3135,8 @@ static void srtp_calc_aead_iv_srtcp(srtp_stream_ctx_t *stream, v128_t *iv, */ static srtp_err_status_t srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, - void *rtcp_hdr, unsigned int *pkt_octet_len) + void *rtcp_hdr, unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, unsigned int use_mki) { srtcp_hdr_t *hdr = (srtcp_hdr_t*)rtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ @@ -2908,9 +3148,10 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, uint32_t seq_num; v128_t iv; uint32_t tseq; + unsigned int mki_size = 0; /* get tag length from stream context */ - tag_len = srtp_auth_get_tag_length(stream->rtcp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); /* * set encryption start and encryption length - if we're not @@ -2934,6 +3175,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, *trailer = 0x00000000; /* set encrypt bit */ } + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len + sizeof(srtcp_trailer_t), session_keys, use_mki); + /* * set the auth_tag pointer to the proper location, which is after * the payload, but before the trailer @@ -2957,8 +3200,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* * Calculating the IV and pass it down to the cipher */ - srtp_calc_aead_iv_srtcp(stream, &iv, seq_num, hdr); - status = srtp_cipher_set_iv(stream->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); if (status) { return srtp_err_status_cipher_fail; } @@ -2971,7 +3214,7 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * If payload encryption is enabled, then the AAD consist of * the RTCP header and the seq# at the end of the packet */ - status = srtp_cipher_set_aad(stream->rtcp_cipher, (uint8_t*)hdr, octets_in_rtcp_header); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, octets_in_rtcp_header); if (status) { return ( srtp_err_status_cipher_fail); } @@ -2981,7 +3224,7 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * the entire packet as described in section 10.3 in revision 07 * of the draft. */ - status = srtp_cipher_set_aad(stream->rtcp_cipher, (uint8_t*)hdr, *pkt_octet_len); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, *pkt_octet_len); if (status) { return ( srtp_err_status_cipher_fail); } @@ -2990,14 +3233,14 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Process the sequence# as AAD */ tseq = *trailer; - status = srtp_cipher_set_aad(stream->rtcp_cipher, (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); if (status) { return ( srtp_err_status_cipher_fail); } /* if we're encrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_encrypt(stream->rtcp_cipher, + status = srtp_cipher_encrypt(session_keys->rtcp_cipher, (uint8_t*)enc_start, &enc_octet_len); if (status) { return srtp_err_status_cipher_fail; @@ -3005,7 +3248,7 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* * Get the tag and append that to the output */ - status = srtp_cipher_get_tag(stream->rtcp_cipher, (uint8_t*)auth_tag, &tag_len); + status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tag_len); if (status) { return ( srtp_err_status_cipher_fail); } @@ -3016,14 +3259,14 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * to run the cipher to get the auth tag. */ unsigned int nolen = 0; - status = srtp_cipher_encrypt(stream->rtcp_cipher, NULL, &nolen); + status = srtp_cipher_encrypt(session_keys->rtcp_cipher, NULL, &nolen); if (status) { return srtp_err_status_cipher_fail; } /* * Get the tag and append that to the output */ - status = srtp_cipher_get_tag(stream->rtcp_cipher, (uint8_t*)auth_tag, &tag_len); + status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tag_len); if (status) { return ( srtp_err_status_cipher_fail); } @@ -3033,6 +3276,9 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* increase the packet length by the length of the auth tag and seq_num*/ *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t)); + /* increase the packet by the mki_size */ + *pkt_octet_len += mki_size; + return srtp_err_status_ok; } @@ -3044,7 +3290,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, */ static srtp_err_status_t srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, - void *srtcp_hdr, unsigned int *pkt_octet_len) + void *srtcp_hdr, unsigned int *pkt_octet_len, + srtp_session_keys_t *session_keys, unsigned int use_mki) { srtcp_hdr_t *hdr = (srtcp_hdr_t*)srtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ @@ -3057,9 +3304,14 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, uint32_t seq_num; v128_t iv; uint32_t tseq; + unsigned int mki_size = 0; /* get tag length from stream context */ - tag_len = srtp_auth_get_tag_length(stream->rtcp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); + + if (use_mki) { + mki_size = session_keys->mki_size; + } /* * set encryption start, encryption length, and trailer @@ -3073,13 +3325,13 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * NOTE: trailer is 32-bit aligned because RTCP 'packets' are always * multiples of 32-bits (RFC 3550 6.1) */ - trailer = (uint32_t*)((char*)hdr + *pkt_octet_len - sizeof(srtcp_trailer_t)); + trailer = (uint32_t*)((char*)hdr + *pkt_octet_len - sizeof(srtcp_trailer_t) - mki_size); /* * We pass the tag down to the cipher when doing GCM mode */ enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header + - sizeof(srtcp_trailer_t)); - auth_tag = (uint8_t*)hdr + *pkt_octet_len - tag_len - sizeof(srtcp_trailer_t); + sizeof(srtcp_trailer_t) + mki_size); + auth_tag = (uint8_t*)hdr + *pkt_octet_len - tag_len - mki_size - sizeof(srtcp_trailer_t); if (*((unsigned char*)trailer) & SRTCP_E_BYTE_BIT) { enc_start = (uint32_t*)hdr + uint32s_in_rtcp_header; @@ -3102,8 +3354,8 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* * Calculate and set the IV */ - srtp_calc_aead_iv_srtcp(stream, &iv, seq_num, hdr); - status = srtp_cipher_set_iv(stream->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); if (status) { return srtp_err_status_cipher_fail; } @@ -3116,7 +3368,7 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * If payload encryption is enabled, then the AAD consist of * the RTCP header and the seq# at the end of the packet */ - status = srtp_cipher_set_aad(stream->rtcp_cipher, (uint8_t*)hdr, octets_in_rtcp_header); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, octets_in_rtcp_header); if (status) { return ( srtp_err_status_cipher_fail); } @@ -3126,7 +3378,7 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * the entire packet as described in section 10.3 in revision 07 * of the draft. */ - status = srtp_cipher_set_aad(stream->rtcp_cipher, (uint8_t*)hdr, + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t))); if (status) { return ( srtp_err_status_cipher_fail); @@ -3137,14 +3389,14 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Process the sequence# as AAD */ tseq = *trailer; - status = srtp_cipher_set_aad(stream->rtcp_cipher, (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); if (status) { return ( srtp_err_status_cipher_fail); } /* if we're decrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_decrypt(stream->rtcp_cipher, (uint8_t*)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t*)enc_start, &enc_octet_len); if (status) { return status; } @@ -3153,14 +3405,14 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Still need to run the cipher to check the tag */ tmp_len = tag_len; - status = srtp_cipher_decrypt(stream->rtcp_cipher, (uint8_t*)auth_tag, &tmp_len); + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tmp_len); if (status) { return status; } } /* decrease the packet length by the length of the auth tag and seq_num*/ - *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t)); + *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t) + mki_size); /* * verify that stream is for received traffic - this check will @@ -3216,6 +3468,11 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, srtp_err_status_t srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { + return srtp_protect_rtcp_mki(ctx, rtcp_hdr, pkt_octet_len, 0, 0); +} + +srtp_err_status_t +srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, unsigned int use_mki, unsigned int mki_index) { srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -3227,6 +3484,8 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { srtp_stream_ctx_t *stream; uint32_t prefix_len; uint32_t seq_num; + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; /* we assume the hdr is 32-bit aligned to start */ @@ -3278,17 +3537,19 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { } } + session_keys = srtp_get_session_keys_with_mki_index(stream, use_mki, mki_index); + /* * Check if this is an AEAD stream (GCM mode). If so, then dispatch * the request to our AEAD handler. */ - if (stream->rtp_cipher->algorithm == SRTP_AES_128_GCM || - stream->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, (unsigned int*)pkt_octet_len); + if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || + session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { + return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, (unsigned int*)pkt_octet_len, session_keys, use_mki); } /* get tag length from stream context */ - tag_len = srtp_auth_get_tag_length(stream->rtcp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); /* * set encryption start and encryption length - if we're not @@ -3313,13 +3574,15 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { *trailer = 0x00000000; /* set encrypt bit */ } + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t), session_keys, use_mki); + /* * set the auth_start and auth_tag pointers to the proper locations * (note that srtpc *always* provides authentication, unlike srtp) */ /* Note: This would need to change for optional mikey data */ auth_start = (uint32_t *)hdr; - auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t); + auth_tag = (uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t) + mki_size; /* perform EKT processing if needed */ srtp_ekt_write_data(stream->ekt, auth_tag, tag_len, pkt_octet_len, @@ -3339,14 +3602,14 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { /* * if we're using rindael counter mode, set nonce and seq */ - if (stream->rtcp_cipher->type->id == SRTP_AES_ICM) { + if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM) { v128_t iv; iv.v32[0] = 0; iv.v32[1] = hdr->ssrc; /* still in network order! */ iv.v32[2] = htonl(seq_num >> 16); iv.v32[3] = htonl(seq_num << 16); - status = srtp_cipher_set_iv(stream->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); } else { v128_t iv; @@ -3356,7 +3619,7 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { iv.v32[1] = 0; iv.v32[2] = 0; iv.v32[3] = htonl(seq_num); - status = srtp_cipher_set_iv(stream->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); } if (status) return srtp_err_status_cipher_fail; @@ -3370,8 +3633,8 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { if (auth_start) { /* put keystream prefix into auth_tag */ - prefix_len = srtp_auth_get_prefix_length(stream->rtcp_auth); - status = srtp_cipher_output(stream->rtcp_cipher, auth_tag, &prefix_len); + prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); + status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag, &prefix_len); debug_print(mod_srtp, "keystream prefix: %s", srtp_octet_string_hex_string(auth_tag, prefix_len)); @@ -3382,20 +3645,20 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { /* if we're encrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_encrypt(stream->rtcp_cipher, + status = srtp_cipher_encrypt(session_keys->rtcp_cipher, (uint8_t *)enc_start, &enc_octet_len); if (status) return srtp_err_status_cipher_fail; } /* initialize auth func context */ - srtp_auth_start(stream->rtcp_auth); + srtp_auth_start(session_keys->rtcp_auth); /* * run auth func over packet (including trailer), and write the * result at auth_tag */ - status = srtp_auth_compute(stream->rtcp_auth, + status = srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start, (*pkt_octet_len) + sizeof(srtcp_trailer_t), auth_tag); @@ -3406,6 +3669,9 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { /* increase the packet length by the length of the auth tag and seq_num*/ *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t)); + + /* increase the packet by the mki_size */ + *pkt_octet_len += mki_size; return srtp_err_status_ok; } @@ -3413,6 +3679,11 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { + return srtp_unprotect_rtcp_mki(ctx, srtcp_hdr, pkt_octet_len, 0); +} + +srtp_err_status_t +srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigned int use_mki) { srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -3429,6 +3700,8 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { uint32_t seq_num; int e_bit_in_packet; /* whether the E-bit was found in the packet */ int sec_serv_confidentiality; /* whether confidentiality was requested */ + unsigned int mki_size = 0; + srtp_session_keys_t *session_keys = NULL; /* we assume the hdr is 32-bit aligned to start */ @@ -3473,14 +3746,27 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { return srtp_err_status_no_ctx; } } - + + /* + * Determine if MKI is being used and what the MKI index is + */ + if (use_mki) { + session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, (const unsigned int*)pkt_octet_len, &mki_size); + + if (session_keys == NULL) + return srtp_err_status_bad_mki; + } else { + session_keys = &stream->session_keys[0]; + } + + /* get tag length from stream context */ - tag_len = srtp_auth_get_tag_length(stream->rtcp_auth); + tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth); /* check the packet length - it must contain at least a full RTCP header, an auth tag (if applicable), and the SRTCP encrypted flag and 31-bit index value */ - if (*pkt_octet_len < (int) (octets_in_rtcp_header + tag_len + sizeof(srtcp_trailer_t))) { + if (*pkt_octet_len < (int) (octets_in_rtcp_header + tag_len + mki_size + sizeof(srtcp_trailer_t))) { return srtp_err_status_bad_param; } @@ -3488,9 +3774,9 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { * Check if this is an AEAD stream (GCM mode). If so, then dispatch * the request to our AEAD handler. */ - if (stream->rtp_cipher->algorithm == SRTP_AES_128_GCM || - stream->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr, (unsigned int*)pkt_octet_len); + if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || + session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { + return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr, (unsigned int*)pkt_octet_len, session_keys, mki_size); } sec_serv_confidentiality = stream->rtcp_services == sec_serv_conf || @@ -3500,7 +3786,7 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { * set encryption start, encryption length, and trailer */ enc_octet_len = *pkt_octet_len - - (octets_in_rtcp_header + tag_len + sizeof(srtcp_trailer_t)); + (octets_in_rtcp_header + tag_len + mki_size + sizeof(srtcp_trailer_t)); /* index & E (encryption) bit follow normal data. hdr->len is the number of words (32-bit) in the normal packet minus 1 */ /* This should point trailer to the word past the end of the @@ -3511,7 +3797,7 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { * multiples of 32-bits (RFC 3550 6.1) */ trailer = (uint32_t *) ((char *) hdr + - *pkt_octet_len -(tag_len + sizeof(srtcp_trailer_t))); + *pkt_octet_len -(tag_len + mki_size + sizeof(srtcp_trailer_t))); e_bit_in_packet = (*((unsigned char *) trailer) & SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT; if (e_bit_in_packet != sec_serv_confidentiality) { @@ -3529,8 +3815,14 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { * (note that srtcp *always* uses authentication, unlike srtp) */ auth_start = (uint32_t *)hdr; - auth_len = *pkt_octet_len - tag_len; - auth_tag = (uint8_t *)hdr + auth_len; + + /* + * The location of the auth tag in the packet needs to know MKI ID + * could be present. The data needed to calculate the Auth tag + * must not include the MKI ID + */ + auth_len = *pkt_octet_len - tag_len - mki_size; + auth_tag = (uint8_t *)hdr + auth_len + mki_size; /* * if EKT is in use, then we make a copy of the tag from the packet, @@ -3560,14 +3852,14 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { /* * if we're using aes counter mode, set nonce and seq */ - if (stream->rtcp_cipher->type->id == SRTP_AES_ICM) { + if (session_keys->rtcp_cipher->type->id == SRTP_AES_ICM) { v128_t iv; iv.v32[0] = 0; iv.v32[1] = hdr->ssrc; /* still in network order! */ iv.v32[2] = htonl(seq_num >> 16); iv.v32[3] = htonl(seq_num << 16); - status = srtp_cipher_set_iv(stream->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); } else { v128_t iv; @@ -3577,17 +3869,17 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { iv.v32[1] = 0; iv.v32[2] = 0; iv.v32[3] = htonl(seq_num); - status = srtp_cipher_set_iv(stream->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); } if (status) return srtp_err_status_cipher_fail; /* initialize auth func context */ - srtp_auth_start(stream->rtcp_auth); + srtp_auth_start(session_keys->rtcp_auth); /* run auth func over packet, put result into tmp_tag */ - status = srtp_auth_compute(stream->rtcp_auth, (uint8_t *)auth_start, + status = srtp_auth_compute(session_keys->rtcp_auth, (uint8_t *)auth_start, auth_len, tmp_tag); debug_print(mod_srtp, "srtcp computed tag: %s", srtp_octet_string_hex_string(tmp_tag, tag_len)); @@ -3604,9 +3896,9 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { * if we're authenticating using a universal hash, put the keystream * prefix into the authentication tag */ - prefix_len = srtp_auth_get_prefix_length(stream->rtcp_auth); + prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); if (prefix_len) { - status = srtp_cipher_output(stream->rtcp_cipher, auth_tag, &prefix_len); + status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag, &prefix_len); debug_print(mod_srtp, "keystream prefix: %s", srtp_octet_string_hex_string(auth_tag, prefix_len)); if (status) @@ -3615,7 +3907,7 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { /* if we're decrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_decrypt(stream->rtcp_cipher, (uint8_t *)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t *)enc_start, &enc_octet_len); if (status) return srtp_err_status_cipher_fail; } @@ -3623,6 +3915,9 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { /* decrease the packet length by the length of the auth tag and seq_num */ *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t)); + /* decrease the packet length by the length of the mki_size */ + *pkt_octet_len -= mki_size; + /* * if EKT is in effect, subtract the EKT data out of the packet * length @@ -3821,6 +4116,33 @@ srtp_profile_get_master_salt_length(srtp_profile_t profile) { } } +srtp_err_status_t +srtp_get_protect_data_added_length(const srtp_policy_t *policy, + uint32_t use_mki, + uint32_t mki_index, + uint32_t is_rtcp, + uint32_t *length) +{ + *length = 0; + + if (use_mki) { + if (mki_index > policy->num_master_keys) + return srtp_err_status_bad_mki; + + *length += policy->keys[mki_index].mki_size; + } + + if (is_rtcp) { + *length += sizeof(srtcp_trailer_t); + *length += policy->rtcp.auth_tag_len; + } else { + *length += policy->rtp.auth_tag_len; + } + + return srtp_err_status_ok; +} + + /* * SRTP debug interface */ diff --git a/test/dtls_srtp_driver.c b/test/dtls_srtp_driver.c index cc2a002d9..37ea79d22 100644 --- a/test/dtls_srtp_driver.c +++ b/test/dtls_srtp_driver.c @@ -45,6 +45,7 @@ #include /* for printf() */ #include "getopt_s.h" /* for local getopt() */ #include "srtp_priv.h" +#include "util.h" srtp_err_status_t test_dtls_srtp(void); @@ -184,7 +185,7 @@ test_dtls_srtp(void) { memset(key, 0xff, key_len); memset(salt, 0xee, salt_len); srtp_append_salt_to_key(key, key_len, salt, salt_len); - policy.key = key; + srtp_update_policy_master_key(&policy, key); /* initialize SRTP policy from profile */ err = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile); diff --git a/test/rtp_decoder.c b/test/rtp_decoder.c index 341079168..bc7701ef0 100644 --- a/test/rtp_decoder.c +++ b/test/rtp_decoder.c @@ -267,8 +267,7 @@ main (int argc, char *argv[]) { fprintf(stderr, "error: unknown security service requested\n"); return -1; } - - policy.key = (uint8_t *) key; + srtp_update_policy_master_key(&policy, (uint8_t *)key); policy.ekt = NULL; policy.next = NULL; policy.window_size = 128; diff --git a/test/rtpw.c b/test/rtpw.c index 763bdeea7..725c1a3af 100644 --- a/test/rtpw.c +++ b/test/rtpw.c @@ -439,7 +439,7 @@ main (int argc, char *argv[]) { } policy.ssrc.type = ssrc_specific; policy.ssrc.value = ssrc; - policy.key = (uint8_t *) key; + srtp_update_policy_master_key(&policy, (uint8_t *)key); policy.ekt = NULL; policy.next = NULL; policy.window_size = 128; @@ -497,7 +497,7 @@ main (int argc, char *argv[]) { */ srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp); srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp); - policy.key = (uint8_t *)key; + srtp_update_policy_master_key(&policy, (uint8_t *)key); policy.ssrc.type = ssrc_specific; policy.ssrc.value = ssrc; policy.window_size = 0; diff --git a/test/srtp_driver.c b/test/srtp_driver.c index 10103a1f9..d3033f19b 100644 --- a/test/srtp_driver.c +++ b/test/srtp_driver.c @@ -51,6 +51,7 @@ #include "util.h" #include "srtp_priv.h" +#include "util.h" #ifdef HAVE_NETINET_IN_H # include @@ -112,10 +113,10 @@ void srtp_do_rejection_timing(const srtp_policy_t *policy); srtp_err_status_t -srtp_test(const srtp_policy_t *policy, int extension_header); +srtp_test(const srtp_policy_t *policy, int extension_header, int mki_index); srtp_err_status_t -srtcp_test(const srtp_policy_t *policy); +srtcp_test(const srtp_policy_t *policy, int mki_index); srtp_err_status_t srtp_session_print_policy(srtp_t srtp); @@ -130,6 +131,9 @@ double mips_estimate(int num_trials, int *ignore); extern uint8_t test_key[46]; +extern uint8_t test_key_2[46]; +extern uint8_t test_mki_id[4]; +extern uint8_t test_mki_id_2[4]; void usage (char *prog_name) @@ -259,21 +263,51 @@ main (int argc, char *argv[]) /* loop over policy array, testing srtp and srtcp for each policy */ while (*policy != NULL) { printf("testing srtp_protect and srtp_unprotect\n"); - if (srtp_test(*policy, 0) == srtp_err_status_ok) { + if (srtp_test(*policy, 0, -1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); exit(1); } + printf("testing srtp_protect and srtp_unprotect with encrypted extensions headers\n"); - if (srtp_test(*policy, 1) == srtp_err_status_ok) { + if (srtp_test(*policy, 1, -1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); exit(1); } printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp\n"); - if (srtcp_test(*policy) == srtp_err_status_ok) { + if (srtcp_test(*policy, -1) == srtp_err_status_ok) { + printf("passed\n\n"); + } else{ + printf("failed\n"); + exit(1); + } + printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI index set to 0\n"); + if (srtp_test(*policy, 0, 0) == srtp_err_status_ok) { + printf("passed\n\n"); + } else{ + printf("failed\n"); + exit(1); + } + printf("testing srtp_protect_rtp and srtp_unprotect_rtp with MKI index set to 1\n"); + if (srtp_test(*policy, 0, 1) == srtp_err_status_ok) { + printf("passed\n\n"); + } else{ + printf("failed\n"); + exit(1); + } + + printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI index set to 0\n"); + if (srtcp_test(*policy, 0) == srtp_err_status_ok) { + printf("passed\n\n"); + } else{ + printf("failed\n"); + exit(1); + } + printf("testing srtp_protect_rtcp and srtp_unprotect_rtcp with MKI index set to 1\n"); + if (srtcp_test(*policy, 1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); @@ -289,14 +323,14 @@ main (int argc, char *argv[]) exit(1); } printf("testing srtp_protect and srtp_unprotect with big policy\n"); - if (srtp_test(big_policy, 0) == srtp_err_status_ok) { + if (srtp_test(big_policy, 0, -1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); exit(1); } printf("testing srtp_protect and srtp_unprotect with big policy and encrypted extensions headers\n"); - if (srtp_test(big_policy, 1) == srtp_err_status_ok) { + if (srtp_test(big_policy, 1, -1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); @@ -311,7 +345,7 @@ main (int argc, char *argv[]) /* run test on wildcard policy */ printf("testing srtp_protect and srtp_unprotect on " "wildcard ssrc policy\n"); - if (srtp_test(&wildcard_policy, 0) == srtp_err_status_ok) { + if (srtp_test(&wildcard_policy, 0, -1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); @@ -319,7 +353,7 @@ main (int argc, char *argv[]) } printf("testing srtp_protect and srtp_unprotect on " "wildcard ssrc policy and encrypted extensions headers\n"); - if (srtp_test(&wildcard_policy, 1) == srtp_err_status_ok) { + if (srtp_test(&wildcard_policy, 1, -1) == srtp_err_status_ok) { printf("passed\n\n"); } else{ printf("failed\n"); @@ -460,7 +494,7 @@ main (int argc, char *argv[]) srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xdecafbad; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -801,7 +835,43 @@ err_check (srtp_err_status_t s) } srtp_err_status_t -srtp_test (const srtp_policy_t *policy, int extension_header) +srtp_test_call_protect(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int mki_index) { + if (mki_index == -1) { + return srtp_protect(srtp_sender, hdr, len); + } else { + return srtp_protect_mki(srtp_sender, hdr, len, 1, mki_index); + } +} + +srtp_err_status_t +srtp_test_call_protect_rtcp(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int mki_index) { + if (mki_index == -1) { + return srtp_protect_rtcp(srtp_sender, hdr, len); + } else { + return srtp_protect_rtcp_mki(srtp_sender, hdr, len, 1, mki_index); + } +} + +srtp_err_status_t +srtp_test_call_unprotect(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int use_mki) { + if (use_mki == -1) { + return srtp_unprotect(srtp_sender, hdr, len); + } else { + return srtp_unprotect_mki(srtp_sender, hdr, len, use_mki); + } +} + +srtp_err_status_t +srtp_test_call_unprotect_rtcp(srtp_t srtp_sender, srtp_hdr_t *hdr, int *len, int use_mki) { + if (use_mki == -1) { + return srtp_unprotect_rtcp(srtp_sender, hdr, len); + } else { + return srtp_unprotect_rtcp_mki(srtp_sender, hdr, len, use_mki); + } +} + +srtp_err_status_t +srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) { int i; srtp_t srtp_sender; @@ -817,16 +887,24 @@ srtp_test (const srtp_policy_t *policy, int extension_header) srtp_policy_t *rcvr_policy; srtp_policy_t tmp_policy; int header = 1; + int use_mki = 0; + + printf("HOOP Inside SRTP Test\n"); + if (mki_index >= 0) + use_mki = 1; if (extension_header) { memcpy(&tmp_policy, policy, sizeof(srtp_policy_t)); tmp_policy.enc_xtn_hdr = &header; tmp_policy.enc_xtn_hdr_count = 1; + printf("HOOP Inside SRTP Test about to call create with extension header\n"); err_check(srtp_create(&srtp_sender, &tmp_policy)); } else { + printf("HOOP Inside SRTP Test about to call create\n"); err_check(srtp_create(&srtp_sender, policy)); } + printf("HOOP Inside SRTP Test after srtp_create\n"); /* print out policy */ err_check(srtp_session_print_policy(srtp_sender)); @@ -871,7 +949,8 @@ srtp_test (const srtp_policy_t *policy, int extension_header) debug_print(mod_driver, "reference packet before protection:\n%s", octet_string_hex_string((uint8_t*)hdr, len)); #endif - err_check(srtp_protect(srtp_sender, hdr, &len)); + printf("HOOP about to call protect\n"); + err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index)); debug_print(mod_driver, "after protection:\n%s", srtp_packet_to_string(hdr, len)); @@ -960,7 +1039,8 @@ srtp_test (const srtp_policy_t *policy, int extension_header) err_check(srtp_create(&srtp_rcvr, rcvr_policy)); - err_check(srtp_unprotect(srtp_rcvr, hdr, &len)); + printf("HOOP about to call unprotect\n"); + err_check(srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki)); debug_print(mod_driver, "after unprotection:\n%s", srtp_packet_to_string(hdr, len)); @@ -991,7 +1071,8 @@ srtp_test (const srtp_policy_t *policy, int extension_header) len = msg_len_enc; /* unprotect a second time - should fail with a replay error */ - status = srtp_unprotect(srtp_rcvr, hdr_enc, &len); + printf("HOOP about to call unprotect a second time\n"); + status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki); if (status != srtp_err_status_replay_fail) { printf("failed with error code %d\n", status); free(hdr); @@ -1014,13 +1095,13 @@ srtp_test (const srtp_policy_t *policy, int extension_header) } /* apply protection */ - err_check(srtp_protect(srtp_sender, hdr, &len)); + err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index)); /* flip bits in packet */ data[extension_header ? 12 : 0] ^= 0xff; /* unprotect, and check for authentication failure */ - status = srtp_unprotect(srtp_rcvr, hdr, &len); + status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki); if (status != srtp_err_status_auth_fail) { printf("failed\n"); free(hdr); @@ -1044,7 +1125,7 @@ srtp_test (const srtp_policy_t *policy, int extension_header) srtp_err_status_t -srtcp_test (const srtp_policy_t *policy) +srtcp_test (const srtp_policy_t *policy, int mki_index) { int i; srtp_t srtcp_sender; @@ -1058,6 +1139,10 @@ srtcp_test (const srtp_policy_t *policy) int tag_length = policy->rtp.auth_tag_len; uint32_t ssrc; srtp_policy_t *rcvr_policy; + int use_mki = 0; + + if (mki_index >= 0) + use_mki = 1; err_check(srtp_create(&srtcp_sender, policy)); @@ -1096,7 +1181,7 @@ srtcp_test (const srtp_policy_t *policy) debug_print(mod_driver, "reference packet before protection:\n%s", octet_string_hex_string((uint8_t*)hdr, len)); #endif - err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len)); + err_check(srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index)); debug_print(mod_driver, "after protection:\n%s", srtp_packet_to_string(hdr, len)); @@ -1173,7 +1258,7 @@ srtcp_test (const srtp_policy_t *policy) err_check(srtp_create(&srtcp_rcvr, rcvr_policy)); - err_check(srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len)); + err_check(srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki)); debug_print(mod_driver, "after unprotection:\n%s", srtp_packet_to_string(hdr, len)); @@ -1204,7 +1289,7 @@ srtcp_test (const srtp_policy_t *policy) len = msg_len_enc; /* unprotect a second time - should fail with a replay error */ - status = srtp_unprotect_rtcp(srtcp_rcvr, hdr_enc, &len); + status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki); if (status != srtp_err_status_replay_fail) { printf("failed with error code %d\n", status); free(hdr); @@ -1224,13 +1309,13 @@ srtcp_test (const srtp_policy_t *policy) len = msg_len_octets; /* apply protection */ - err_check(srtp_protect_rtcp(srtcp_sender, hdr, &len)); + err_check(srtp_test_call_protect_rtcp(srtcp_sender, hdr, &len, mki_index)); /* flip bits in packet */ data[0] ^= 0xff; /* unprotect, and check for authentication failure */ - status = srtp_unprotect_rtcp(srtcp_rcvr, hdr, &len); + status = srtp_test_call_unprotect_rtcp(srtcp_rcvr, hdr, &len, use_mki); if (status != srtp_err_status_auth_fail) { printf("failed\n"); free(hdr); @@ -1268,6 +1353,7 @@ srtp_session_print_policy (srtp_t srtp) "inbound" }; srtp_stream_t stream; + srtp_session_keys_t *session_keys = NULL; /* sanity checking */ if (srtp == NULL) { @@ -1277,6 +1363,7 @@ srtp_session_print_policy (srtp_t srtp) /* if there's a template stream, print it out */ if (srtp->stream_template != NULL) { stream = srtp->stream_template; + session_keys = &stream->session_keys[0]; printf("# SSRC: any %s\r\n" "# rtp cipher: %s\r\n" "# rtp auth: %s\r\n" @@ -1287,11 +1374,11 @@ srtp_session_print_policy (srtp_t srtp) "# window size: %lu\r\n" "# tx rtx allowed:%s\r\n", direction[stream->direction], - stream->rtp_cipher->type->description, - stream->rtp_auth->type->description, + session_keys->rtp_cipher->type->description, + session_keys->rtp_auth->type->description, serv_descr[stream->rtp_services], - stream->rtcp_cipher->type->description, - stream->rtcp_auth->type->description, + session_keys->rtcp_cipher->type->description, + session_keys->rtcp_auth->type->description, serv_descr[stream->rtcp_services], srtp_rdbx_get_window_size(&stream->rtp_rdbx), stream->allow_repeat_tx ? "true" : "false"); @@ -1317,6 +1404,7 @@ srtp_session_print_policy (srtp_t srtp) if (stream->rtp_services > sec_serv_conf_and_auth) { return srtp_err_status_bad_param; } + session_keys = &stream->session_keys[0]; printf("# SSRC: 0x%08x\r\n" "# rtp cipher: %s\r\n" @@ -1328,11 +1416,11 @@ srtp_session_print_policy (srtp_t srtp) "# window size: %lu\r\n" "# tx rtx allowed:%s\r\n", stream->ssrc, - stream->rtp_cipher->type->description, - stream->rtp_auth->type->description, + session_keys->rtp_cipher->type->description, + session_keys->rtp_auth->type->description, serv_descr[stream->rtp_services], - stream->rtcp_cipher->type->description, - stream->rtcp_auth->type->description, + session_keys->rtcp_cipher->type->description, + session_keys->rtcp_auth->type->description, serv_descr[stream->rtcp_services], srtp_rdbx_get_window_size(&stream->rtp_rdbx), stream->allow_repeat_tx ? "true" : "false"); @@ -1525,7 +1613,7 @@ srtp_validate () srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -1846,7 +1934,7 @@ srtp_validate_encrypted_extensions_headers() { srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key_ext_headers; + srtp_update_policy_master_key(&policy, test_key_ext_headers); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -1965,7 +2053,7 @@ srtp_validate_encrypted_extensions_headers_gcm() { srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key_ext_headers; + srtp_update_policy_master_key(&policy, test_key_ext_headers); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2080,7 +2168,7 @@ srtp_validate_aes_256 () srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = aes_256_test_key; + srtp_update_policy_master_key(&policy, aes_256_test_key); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2211,7 +2299,7 @@ srtp_test_empty_payload() srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2289,7 +2377,7 @@ srtp_test_empty_payload_gcm() srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2417,7 +2505,7 @@ srtp_test_remove_stream () srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2482,7 +2570,7 @@ srtp_test_update() { policy.allow_repeat_tx = 0; policy.next = NULL; policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); /* create a send and recive ctx with defualt profile and test_key */ status = srtp_create(&srtp_recv, &policy); @@ -2529,7 +2617,7 @@ srtp_test_update() { /* update send ctx with same test_key t verify update works*/ policy.ssrc.type = ssrc_any_outbound; - policy.key = test_key; + srtp_update_policy_master_key(&policy, test_key); status = srtp_update(srtp_snd, &policy); if (status) return status; @@ -2553,7 +2641,7 @@ srtp_test_update() { /* update send ctx to use test_alt_key */ policy.ssrc.type = ssrc_any_outbound; - policy.key = test_alt_key; + srtp_update_policy_master_key(&policy, test_alt_key); status = srtp_update(srtp_snd, &policy); if (status) return status; @@ -2580,7 +2668,7 @@ srtp_test_update() { srtp_t srtp_recv_roc_0; policy.ssrc.type = ssrc_any_inbound; - policy.key = test_alt_key; + srtp_update_policy_master_key(&policy, test_alt_key); status = srtp_create(&srtp_recv_roc_0, &policy); if (status) return status; @@ -2596,7 +2684,7 @@ srtp_test_update() { /* update recive ctx to use test_alt_key */ policy.ssrc.type = ssrc_any_inbound; - policy.key = test_alt_key; + srtp_update_policy_master_key(&policy, test_alt_key); status = srtp_update(srtp_recv, &policy); if (status) return status; @@ -2632,6 +2720,14 @@ unsigned char test_key[46] = { 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 }; +unsigned char test_key_2[46] = { + 0xf0, 0xf0, 0x49, 0x14, 0xb5, 0x13, 0xf2, 0x76, + 0x3a, 0x1b, 0x1f, 0xa1, 0x30, 0xf1, 0x0e, 0x29, + 0x98, 0xf6, 0xf6, 0xe4, 0x3e, 0x43, 0x09, 0xd1, + 0xe6, 0x22, 0xa0, 0xe3, 0x32, 0xb9, 0xf1, 0xb6, + 0xc3, 0x17, 0xf2, 0xda, 0xbe, 0x35, 0x77, 0x93, + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 +}; const srtp_policy_t default_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ @@ -2651,7 +2747,29 @@ const srtp_policy_t default_policy = { 10, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2678,7 +2796,29 @@ const srtp_policy_t aes_only_policy = { 0, /* auth tag length in octets */ sec_serv_conf /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2705,7 +2845,29 @@ const srtp_policy_t hmac_only_policy = { 4, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* Number of Master keys associated with the policy */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2733,7 +2895,29 @@ const srtp_policy_t aes128_gcm_8_policy = { 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2760,7 +2944,29 @@ const srtp_policy_t aes128_gcm_8_cauth_policy = { 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 1, NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2787,7 +2993,29 @@ const srtp_policy_t aes256_gcm_8_policy = { 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2814,7 +3042,29 @@ const srtp_policy_t aes256_gcm_8_cauth_policy = { 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2842,7 +3092,29 @@ const srtp_policy_t null_policy = { 0, /* auth tag length in octets */ sec_serv_none /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2861,6 +3133,15 @@ unsigned char test_256_key[46] = { 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2 }; +unsigned char test_256_key_2[46] = { + 0xe1, 0xf9, 0x7a, 0x0d, 0x3e, 0x01, 0x8b, 0xe0, + 0xd6, 0x4f, 0xa3, 0x2c, 0x06, 0xde, 0x41, 0x39, + 0x0e, 0xc6, 0x75, 0xad, 0x49, 0x8a, 0xfe, 0xeb, + 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6, 0xc1, 0x73, + 0x3b, 0x04, 0x80, 0x3d, 0xe5, 0x1e, 0xe7, 0xc9, + 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2 +}; + const srtp_policy_t aes_256_hmac_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { /* SRTP policy */ @@ -2879,7 +3160,29 @@ const srtp_policy_t aes_256_hmac_policy = { 10, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - test_256_key, + { + { + test_256_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_256_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2920,7 +3223,29 @@ const srtp_policy_t hmac_only_with_ekt_policy = { 4, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 2, /* indicates the number of Master keys */ &ekt_test_policy, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2975,7 +3300,29 @@ const srtp_policy_t wildcard_policy = { 10, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - test_key, + { + { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + }, + { + NULL, + NULL, + 0 + } + }, + 1, NULL, 128, /* replay window size */ 0, /* retransmission not allowed */ diff --git a/test/util.c b/test/util.c index c75ab3762..aba0c8446 100644 --- a/test/util.c +++ b/test/util.c @@ -183,3 +183,18 @@ int base64_string_to_octet_string (char *out, int *pad, char *in, int len) return i; } +unsigned char test_mki_id[TEST_MKI_ID_SIZE] = { + 0xe1, 0xf9, 0x7a, 0x0d +}; + +unsigned char test_mki_id_2[TEST_MKI_ID_SIZE] = { + 0xf3, 0xa1, 0x46, 0x71 +}; + +void srtp_update_policy_master_key(srtp_policy_t *policy, uint8_t *key) +{ + policy->num_master_keys = 1; + policy->keys[0].key = key; + policy->keys[0].mki_id = test_mki_id; + policy->keys[0].mki_size = TEST_MKI_ID_SIZE; +} diff --git a/test/util.h b/test/util.h index 1dbc40685..2e17a99f7 100644 --- a/test/util.h +++ b/test/util.h @@ -44,10 +44,16 @@ #ifndef _UTIL_H #define _UTIL_H +#include "srtp.h" + #define MAX_PRINT_STRING_LEN 1024 +#define TEST_MKI_ID_SIZE 4 + + int hex_string_to_octet_string(char *raw, char *hex, int len); char * octet_string_hex_string(const void *s, int length); int base64_string_to_octet_string(char *raw, int *pad, char *base64, int len); +void srtp_update_policy_master_key(srtp_policy_t *policy, uint8_t *key); #endif From 89a288b48749ba311858717f2dedc5ce43a2f4bf Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Thu, 22 Dec 2016 16:22:47 -0500 Subject: [PATCH 02/10] Made the Master Keys Dynamic instead of caping them at only 4 master keys. Also kept key around in the policy to keep as much backward compatiblity as possible --- include/srtp.h | 15 +- include/srtp_priv.h | 8 +- srtp/srtp.c | 115 ++++++++----- test/dtls_srtp_driver.c | 3 +- test/rtp_decoder.c | 2 +- test/rtpw.c | 4 +- test/srtp_driver.c | 350 ++++++++++------------------------------ test/util.c | 16 -- test/util.h | 6 - 9 files changed, 180 insertions(+), 339 deletions(-) diff --git a/include/srtp.h b/include/srtp.h index 5401be364..f2cf4dfa7 100644 --- a/include/srtp.h +++ b/include/srtp.h @@ -90,11 +90,16 @@ extern "C" { /** * SRTP_MAX_NUM_MASTER_KEYS is the maximum number of Master keys for - * MKI supported by libSRTP. Can look at making this dynamic in the - * future. + * MKI supported by libSRTP. * */ -#define SRTP_MAX_NUM_MASTER_KEYS 4 +#define SRTP_MAX_NUM_MASTER_KEYS 16 + +/** + * SRTP_MAX_MKI_LEN is the maximum size the MKI could be which is + * 128 bytes + */ +#define SRTP_MAX_MKI_LEN 128 /* * SRTP_AEAD_SALT_LEN is the length of the SALT values used with @@ -420,7 +425,9 @@ typedef struct srtp_policy_t { */ srtp_crypto_policy_t rtp; /**< SRTP crypto policy. */ srtp_crypto_policy_t rtcp; /**< SRTCP crypto policy. */ - srtp_master_key_t keys[SRTP_MAX_NUM_MASTER_KEYS]; /** Array of Master Key structures */ + unsigned char *key; /**< Pointer to the SRTP master key for + * this stream. */ + srtp_master_key_t **keys; /** Array of Master Key structures */ unsigned long num_master_keys; /** Number of master keys */ srtp_ekt_policy_t ekt; /**< Pointer to the EKT policy structure * for this stream (if any) */ diff --git a/include/srtp_priv.h b/include/srtp_priv.h index 51e1babb1..8e8576e56 100644 --- a/include/srtp_priv.h +++ b/include/srtp_priv.h @@ -78,14 +78,16 @@ srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc); * srtp_stream_init_keys(s, k) (re)initializes the srtp_stream_t s by * deriving all of the needed keys using the KDF and the key k. */ -srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t master_key, const unsigned int current_mki_index); +srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, const unsigned int current_mki_index); /* * srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s by * deriving all of the needed keys for all the master keys using the KDF and the keys from k. */ -srtp_err_status_t srtp_steam_init_all_master_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t keys[SRTP_MAX_NUM_MASTER_KEYS], +srtp_err_status_t srtp_steam_init_all_master_keys(srtp_stream_ctx_t *srtp, + unsigned char *key, + srtp_master_key_t **keys, const unsigned int max_master_keys); /* @@ -133,7 +135,7 @@ typedef struct srtp_session_keys_t { typedef struct srtp_stream_ctx_t_ { uint32_t ssrc; - srtp_session_keys_t session_keys[SRTP_MAX_NUM_MASTER_KEYS]; + srtp_session_keys_t *session_keys; unsigned int num_master_keys; srtp_rdbx_t rtp_rdbx; srtp_sec_serv_t rtp_services; diff --git a/srtp/srtp.c b/srtp/srtp.c index 27f164c6e..fc3a44434 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -178,6 +178,8 @@ srtp_stream_free(srtp_stream_ctx_t *str) { } } + srtp_crypto_free(str->session_keys); + if (str->enc_xtn_hdr) { srtp_crypto_free(str->enc_xtn_hdr); } @@ -212,7 +214,16 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, memset(str, 0, sizeof(srtp_stream_ctx_t)); *str_ptr = str; - str->num_master_keys = p->num_master_keys; + /* To keep backwards API compatible if someone is using multiple master + * keys then key should be set to NULL + */ + if (p->key != NULL) { + str->num_master_keys = 1; + } else { + str->num_master_keys = p->num_master_keys; + } + + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); for (i = 0; i < str->num_master_keys; i++) { session_keys = &str->session_keys[i]; @@ -477,6 +488,7 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, *str_ptr = str; str->num_master_keys = stream_template->num_master_keys; + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); for (i = 0; i < stream_template->num_master_keys; i++){ session_keys = &str->session_keys[i]; @@ -490,15 +502,17 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, session_keys->rtcp_auth = template_session_keys->rtcp_auth; session_keys->mki_size = template_session_keys->mki_size; - session_keys->mki_id = srtp_crypto_alloc(template_session_keys->mki_size); + if (template_session_keys->mki_size == 0) { + session_keys->mki_id = NULL; + } else { + session_keys->mki_id = srtp_crypto_alloc(template_session_keys->mki_size); - if (session_keys->mki_id == NULL) { - return srtp_err_status_init_fail; + if (session_keys->mki_id == NULL) { + return srtp_err_status_init_fail; + } + memset(session_keys->mki_id, 0x0, session_keys->mki_size); + memcpy(session_keys->mki_id, template_session_keys->mki_id, session_keys->mki_size); } - - memset(session_keys->mki_id, 0x0, session_keys->mki_size); - memcpy(session_keys->mki_id, template_session_keys->mki_id, session_keys->mki_size); - /* Copy the salt values */ memcpy(session_keys->salt, template_session_keys->salt, SRTP_AEAD_SALT_LEN); memcpy(session_keys->c_salt, template_session_keys->c_salt, SRTP_AEAD_SALT_LEN); @@ -540,7 +554,6 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, /* defensive coding */ str->next = NULL; - return srtp_err_status_ok; } @@ -739,12 +752,19 @@ srtp_validate_policy_master_keys(const srtp_policy_t *policy) { int i = 0; - if (policy->num_master_keys <= 0) - return 0; - - for (i = 0; i < policy->num_master_keys; i++) { - if (policy->keys[i].key == NULL) + if (policy->key == NULL) { + if (policy->num_master_keys <= 0) return 0; + + if (policy->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) + return 0; + + for (i = 0; i < policy->num_master_keys; i++) { + if (policy->keys[i]->key == NULL) + return 0; + if (policy->keys[i]->mki_size > SRTP_MAX_MKI_LEN) + return 0; + } } return 1; @@ -758,6 +778,7 @@ srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t *stream, unsigned int use return &stream->session_keys[mki_index]; } } + return &stream->session_keys[0]; } @@ -779,18 +800,29 @@ srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, un } srtp_err_status_t -srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t keys[SRTP_MAX_NUM_MASTER_KEYS], +srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, + unsigned char *key, + srtp_master_key_t **keys, const unsigned int max_master_keys) { int i = 0; srtp_err_status_t status = srtp_err_status_ok; + srtp_master_key_t single_master_key; + + if ( key != NULL ) { + srtp->num_master_keys = 1; + single_master_key.key = key; + single_master_key.mki_id = NULL; + single_master_key.mki_size = 0; + status = srtp_stream_init_keys(srtp, &single_master_key, 0); + } else { + srtp->num_master_keys = max_master_keys; - srtp->num_master_keys = max_master_keys; - - for (i = 0; i < srtp->num_master_keys && i < SRTP_MAX_NUM_MASTER_KEYS; i++) { - status = srtp_stream_init_keys(srtp, keys[i], i); + for (i = 0; i < srtp->num_master_keys && i < SRTP_MAX_NUM_MASTER_KEYS; i++) { + status = srtp_stream_init_keys(srtp, keys[i], i); - if (status) { - return status; + if (status) { + return status; + } } } @@ -798,7 +830,7 @@ srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_ } srtp_err_status_t -srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t master_key, const unsigned int current_mki_index) { +srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, const unsigned int current_mki_index) { srtp_err_status_t stat; srtp_kdf_t kdf; uint8_t tmp_key[MAX_SRTP_KEY_LEN]; @@ -806,24 +838,26 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, const srtp_master_key_t master_ke int rtp_base_key_len, rtp_salt_len; int rtcp_base_key_len, rtcp_salt_len; srtp_session_keys_t *session_keys = NULL; - unsigned char *key = master_key.key; + unsigned char *key = master_key->key; /* If RTP or RTCP have a key length > AES-128, assume matching kdf. */ /* TODO: kdf algorithm, master key length, and master salt length should * be part of srtp_policy_t. */ - session_keys = &srtp->session_keys[current_mki_index]; - session_keys->mki_id = srtp_crypto_alloc(master_key.mki_size); + if ( master_key->mki_size != 0 ) { + session_keys->mki_id = srtp_crypto_alloc(master_key->mki_size); - if (session_keys->mki_id == NULL) { - return srtp_err_status_init_fail; + if (session_keys->mki_id == NULL) { + return srtp_err_status_init_fail; + } + memset(session_keys->mki_id, 0x0, master_key->mki_size); + memcpy(session_keys->mki_id, master_key->mki_id, master_key->mki_size); + } else { + session_keys->mki_id = NULL; } - memset(session_keys->mki_id, 0x0, master_key.mki_size); - memcpy(session_keys->mki_id, master_key.mki_id, master_key.mki_size); - - session_keys->mki_size = master_key.mki_size; + session_keys->mki_size = master_key->mki_size; rtp_keylen = srtp_cipher_get_key_length(session_keys->rtp_cipher); rtcp_keylen = srtp_cipher_get_key_length(session_keys->rtcp_cipher); @@ -1150,7 +1184,7 @@ srtp_stream_init(srtp_stream_ctx_t *srtp, /* DAM - no RTCP key limit at present */ /* initialize keys */ - err = srtp_stream_init_all_master_keys(srtp, p->keys, p->num_master_keys); + err = srtp_stream_init_all_master_keys(srtp, p->key, p->keys, p->num_master_keys); if (err) { srtp_rdbx_dealloc(&srtp->rtp_rdbx); return err; @@ -1427,12 +1461,14 @@ srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, const unsigned in base_mki_start_location -= tag_len; for (i = 0; i < stream->num_master_keys; i++) { - *mki_size = stream->session_keys[i].mki_size; - mki_start_location = base_mki_start_location - *mki_size; - - if ( mki_start_location >= *mki_size && - memcmp(hdr + mki_start_location, stream->session_keys[i].mki_id, *mki_size) == 0 ) { - return &stream->session_keys[i]; + if (stream->session_keys[i].mki_size != 0) { + *mki_size = stream->session_keys[i].mki_size; + mki_start_location = base_mki_start_location - *mki_size; + + if ( mki_start_location >= *mki_size && + memcmp(hdr + mki_start_location, stream->session_keys[i].mki_id, *mki_size) == 0 ) { + return &stream->session_keys[i]; + } } } @@ -1857,6 +1893,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * srtp_protect() and srtp_unprotect() will fail this test in one of * those functions. */ + if (stream->direction != dir_srtp_sender) { if (stream->direction == dir_unknown) { stream->direction = dir_srtp_sender; @@ -4129,7 +4166,7 @@ srtp_get_protect_data_added_length(const srtp_policy_t *policy, if (mki_index > policy->num_master_keys) return srtp_err_status_bad_mki; - *length += policy->keys[mki_index].mki_size; + *length += policy->keys[mki_index]->mki_size; } if (is_rtcp) { diff --git a/test/dtls_srtp_driver.c b/test/dtls_srtp_driver.c index 37ea79d22..39a1d4521 100644 --- a/test/dtls_srtp_driver.c +++ b/test/dtls_srtp_driver.c @@ -45,7 +45,6 @@ #include /* for printf() */ #include "getopt_s.h" /* for local getopt() */ #include "srtp_priv.h" -#include "util.h" srtp_err_status_t test_dtls_srtp(void); @@ -185,7 +184,7 @@ test_dtls_srtp(void) { memset(key, 0xff, key_len); memset(salt, 0xee, salt_len); srtp_append_salt_to_key(key, key_len, salt, salt_len); - srtp_update_policy_master_key(&policy, key); + policy.key = key; /* initialize SRTP policy from profile */ err = srtp_crypto_policy_set_from_profile_for_rtp(&policy.rtp, profile); diff --git a/test/rtp_decoder.c b/test/rtp_decoder.c index bc7701ef0..6f2bee268 100644 --- a/test/rtp_decoder.c +++ b/test/rtp_decoder.c @@ -267,7 +267,7 @@ main (int argc, char *argv[]) { fprintf(stderr, "error: unknown security service requested\n"); return -1; } - srtp_update_policy_master_key(&policy, (uint8_t *)key); + policy.key = (uint8_t *) key; policy.ekt = NULL; policy.next = NULL; policy.window_size = 128; diff --git a/test/rtpw.c b/test/rtpw.c index 725c1a3af..0276a813e 100644 --- a/test/rtpw.c +++ b/test/rtpw.c @@ -439,7 +439,7 @@ main (int argc, char *argv[]) { } policy.ssrc.type = ssrc_specific; policy.ssrc.value = ssrc; - srtp_update_policy_master_key(&policy, (uint8_t *)key); + policy.key = (uint8_t *)key; policy.ekt = NULL; policy.next = NULL; policy.window_size = 128; @@ -497,7 +497,7 @@ main (int argc, char *argv[]) { */ srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtp); srtp_crypto_policy_set_null_cipher_hmac_null(&policy.rtcp); - srtp_update_policy_master_key(&policy, (uint8_t *)key); + policy.key = (uint8_t *)key; policy.ssrc.type = ssrc_specific; policy.ssrc.value = ssrc; policy.window_size = 0; diff --git a/test/srtp_driver.c b/test/srtp_driver.c index d3033f19b..1554826cf 100644 --- a/test/srtp_driver.c +++ b/test/srtp_driver.c @@ -1,3 +1,4 @@ + /* * srtp_driver.c * @@ -130,10 +131,29 @@ srtp_packet_to_string(srtp_hdr_t *hdr, int packet_len); double mips_estimate(int num_trials, int *ignore); +#define TEST_MKI_ID_SIZE 4 + extern uint8_t test_key[46]; extern uint8_t test_key_2[46]; -extern uint8_t test_mki_id[4]; -extern uint8_t test_mki_id_2[4]; +extern uint8_t test_mki_id[TEST_MKI_ID_SIZE]; +extern uint8_t test_mki_id_2[TEST_MKI_ID_SIZE]; + +srtp_master_key_t master_key_1 = { + test_key, + test_mki_id, + TEST_MKI_ID_SIZE +}; + +srtp_master_key_t master_key_2 = { + test_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE +}; + +srtp_master_key_t *test_keys[2] = { + &master_key_1, + &master_key_2 +}; void usage (char *prog_name) @@ -494,7 +514,7 @@ main (int argc, char *argv[]) srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xdecafbad; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -889,7 +909,6 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) int header = 1; int use_mki = 0; - printf("HOOP Inside SRTP Test\n"); if (mki_index >= 0) use_mki = 1; @@ -897,14 +916,11 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) memcpy(&tmp_policy, policy, sizeof(srtp_policy_t)); tmp_policy.enc_xtn_hdr = &header; tmp_policy.enc_xtn_hdr_count = 1; - printf("HOOP Inside SRTP Test about to call create with extension header\n"); err_check(srtp_create(&srtp_sender, &tmp_policy)); } else { - printf("HOOP Inside SRTP Test about to call create\n"); err_check(srtp_create(&srtp_sender, policy)); } - printf("HOOP Inside SRTP Test after srtp_create\n"); /* print out policy */ err_check(srtp_session_print_policy(srtp_sender)); @@ -949,7 +965,6 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) debug_print(mod_driver, "reference packet before protection:\n%s", octet_string_hex_string((uint8_t*)hdr, len)); #endif - printf("HOOP about to call protect\n"); err_check(srtp_test_call_protect(srtp_sender, hdr, &len, mki_index)); debug_print(mod_driver, "after protection:\n%s", @@ -1039,7 +1054,6 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) err_check(srtp_create(&srtp_rcvr, rcvr_policy)); - printf("HOOP about to call unprotect\n"); err_check(srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki)); debug_print(mod_driver, "after unprotection:\n%s", @@ -1071,7 +1085,6 @@ srtp_test (const srtp_policy_t *policy, int extension_header, int mki_index) len = msg_len_enc; /* unprotect a second time - should fail with a replay error */ - printf("HOOP about to call unprotect a second time\n"); status = srtp_test_call_unprotect(srtp_rcvr, hdr, &len, use_mki); if (status != srtp_err_status_replay_fail) { printf("failed with error code %d\n", status); @@ -1613,7 +1626,7 @@ srtp_validate () srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -1934,7 +1947,7 @@ srtp_validate_encrypted_extensions_headers() { srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, test_key_ext_headers); + policy.key = test_key_ext_headers; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2053,7 +2066,7 @@ srtp_validate_encrypted_extensions_headers_gcm() { srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, test_key_ext_headers); + policy.key = test_key_ext_headers; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2168,7 +2181,7 @@ srtp_validate_aes_256 () srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, aes_256_test_key); + policy.key = aes_256_test_key; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2299,7 +2312,7 @@ srtp_test_empty_payload() srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2377,7 +2390,7 @@ srtp_test_empty_payload_gcm() srtp_crypto_policy_set_aes_gcm_128_8_auth(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2505,7 +2518,7 @@ srtp_test_remove_stream () srtp_crypto_policy_set_rtcp_default(&policy.rtcp); policy.ssrc.type = ssrc_specific; policy.ssrc.value = 0xcafebabe; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; policy.ekt = NULL; policy.window_size = 128; policy.allow_repeat_tx = 0; @@ -2570,7 +2583,7 @@ srtp_test_update() { policy.allow_repeat_tx = 0; policy.next = NULL; policy.ssrc.type = ssrc_any_outbound; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; /* create a send and recive ctx with defualt profile and test_key */ status = srtp_create(&srtp_recv, &policy); @@ -2617,7 +2630,7 @@ srtp_test_update() { /* update send ctx with same test_key t verify update works*/ policy.ssrc.type = ssrc_any_outbound; - srtp_update_policy_master_key(&policy, test_key); + policy.key = test_key; status = srtp_update(srtp_snd, &policy); if (status) return status; @@ -2641,7 +2654,7 @@ srtp_test_update() { /* update send ctx to use test_alt_key */ policy.ssrc.type = ssrc_any_outbound; - srtp_update_policy_master_key(&policy, test_alt_key); + policy.key = test_alt_key; status = srtp_update(srtp_snd, &policy); if (status) return status; @@ -2668,7 +2681,7 @@ srtp_test_update() { srtp_t srtp_recv_roc_0; policy.ssrc.type = ssrc_any_inbound; - srtp_update_policy_master_key(&policy, test_alt_key); + policy.key = test_alt_key; status = srtp_create(&srtp_recv_roc_0, &policy); if (status) return status; @@ -2684,7 +2697,7 @@ srtp_test_update() { /* update recive ctx to use test_alt_key */ policy.ssrc.type = ssrc_any_inbound; - srtp_update_policy_master_key(&policy, test_alt_key); + policy.key = test_alt_key; status = srtp_update(srtp_recv, &policy); if (status) return status; @@ -2729,6 +2742,14 @@ unsigned char test_key_2[46] = { 0xb6, 0x96, 0x0b, 0x3a, 0xab, 0xe6 }; +unsigned char test_mki_id[TEST_MKI_ID_SIZE] = { + 0xe1, 0xf9, 0x7a, 0x0d +}; + +unsigned char test_mki_id_2[TEST_MKI_ID_SIZE] = { + 0xf3, 0xa1, 0x46, 0x71 +}; + const srtp_policy_t default_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { /* SRTP policy */ @@ -2747,28 +2768,8 @@ const srtp_policy_t default_policy = { 10, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -2796,28 +2797,8 @@ const srtp_policy_t aes_only_policy = { 0, /* auth tag length in octets */ sec_serv_conf /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -2845,28 +2826,8 @@ const srtp_policy_t hmac_only_policy = { 4, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* Number of Master keys associated with the policy */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -2895,28 +2856,8 @@ const srtp_policy_t aes128_gcm_8_policy = { 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -2944,29 +2885,9 @@ const srtp_policy_t aes128_gcm_8_cauth_policy = { 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, - 1, + test_key, + NULL, + 0, NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ @@ -2993,28 +2914,8 @@ const srtp_policy_t aes256_gcm_8_policy = { 8, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -3042,28 +2943,8 @@ const srtp_policy_t aes256_gcm_8_cauth_policy = { 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -3092,28 +2973,8 @@ const srtp_policy_t null_policy = { 0, /* auth tag length in octets */ sec_serv_none /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -3142,6 +3003,23 @@ unsigned char test_256_key_2[46] = { 0x64, 0x23, 0xab, 0x5b, 0x78, 0xd2 }; +srtp_master_key_t master_256_key_1 = { + test_256_key, + test_mki_id, + TEST_MKI_ID_SIZE +}; + +srtp_master_key_t master_256_key_2 = { + test_256_key_2, + test_mki_id_2, + TEST_MKI_ID_SIZE +}; + +srtp_master_key_t *test_256_keys[2] = { + &master_key_1, + &master_key_2 +}; + const srtp_policy_t aes_256_hmac_policy = { { ssrc_any_outbound, 0 }, /* SSRC */ { /* SRTP policy */ @@ -3160,28 +3038,8 @@ const srtp_policy_t aes_256_hmac_policy = { 10, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { - { - test_256_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_256_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_256_keys, 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -3223,28 +3081,8 @@ const srtp_policy_t hmac_only_with_ekt_policy = { 4, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - test_key_2, - test_mki_id_2, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, + NULL, + (srtp_master_key_t **)test_keys, 2, /* indicates the number of Master keys */ &ekt_test_policy, /* indicates that EKT is not in use */ 128, /* replay window size */ @@ -3300,29 +3138,9 @@ const srtp_policy_t wildcard_policy = { 10, /* auth tag length in octets */ sec_serv_conf_and_auth /* security services flag */ }, - { - { - test_key, - test_mki_id, - TEST_MKI_ID_SIZE - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - }, - { - NULL, - NULL, - 0 - } - }, - 1, + test_key, + NULL, + 0, NULL, 128, /* replay window size */ 0, /* retransmission not allowed */ diff --git a/test/util.c b/test/util.c index aba0c8446..f54a5b9fe 100644 --- a/test/util.c +++ b/test/util.c @@ -182,19 +182,3 @@ int base64_string_to_octet_string (char *out, int *pad, char *in, int len) *pad = j; return i; } - -unsigned char test_mki_id[TEST_MKI_ID_SIZE] = { - 0xe1, 0xf9, 0x7a, 0x0d -}; - -unsigned char test_mki_id_2[TEST_MKI_ID_SIZE] = { - 0xf3, 0xa1, 0x46, 0x71 -}; - -void srtp_update_policy_master_key(srtp_policy_t *policy, uint8_t *key) -{ - policy->num_master_keys = 1; - policy->keys[0].key = key; - policy->keys[0].mki_id = test_mki_id; - policy->keys[0].mki_size = TEST_MKI_ID_SIZE; -} diff --git a/test/util.h b/test/util.h index 2e17a99f7..1dbc40685 100644 --- a/test/util.h +++ b/test/util.h @@ -44,16 +44,10 @@ #ifndef _UTIL_H #define _UTIL_H -#include "srtp.h" - #define MAX_PRINT_STRING_LEN 1024 -#define TEST_MKI_ID_SIZE 4 - - int hex_string_to_octet_string(char *raw, char *hex, int len); char * octet_string_hex_string(const void *s, int length); int base64_string_to_octet_string(char *raw, int *pad, char *base64, int len); -void srtp_update_policy_master_key(srtp_policy_t *policy, uint8_t *key); #endif From 6c339f7c342374b75639a98fe4dcc3e561dac00d Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Tue, 3 Jan 2017 13:45:18 -0500 Subject: [PATCH 03/10] Fixing test where MKI should be possible where the policy was not setup correctly. --- test/srtp_driver.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/srtp_driver.c b/test/srtp_driver.c index 1554826cf..e801f821a 100644 --- a/test/srtp_driver.c +++ b/test/srtp_driver.c @@ -2885,9 +2885,9 @@ const srtp_policy_t aes128_gcm_8_cauth_policy = { 8, /* auth tag length in octets */ sec_serv_auth /* security services flag */ }, - test_key, NULL, - 0, + (srtp_master_key_t **)test_keys, + 2, /* indicates the number of Master keys */ NULL, /* indicates that EKT is not in use */ 128, /* replay window size */ 0, /* retransmission not allowed */ From bac6076e7b558158538a95ff24ddc8a676b50548 Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Tue, 3 Jan 2017 13:48:27 -0500 Subject: [PATCH 04/10] Fixing issue where RTCP is not encrypted but only authenticated by AES GCM --- srtp/srtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srtp/srtp.c b/srtp/srtp.c index fc3a44434..edbbacf24 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -3416,7 +3416,7 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * of the draft. */ status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, - (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t))); + (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t) - mki_size)); if (status) { return ( srtp_err_status_cipher_fail); } From def537afd0c4f4a8a6348ff8d4e9c0f833752846 Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Wed, 18 Jan 2017 09:49:51 -0500 Subject: [PATCH 05/10] Fixing memory leak found in code review --- srtp/srtp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srtp/srtp.c b/srtp/srtp.c index edbbacf24..5896a5acd 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -431,6 +431,8 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat session_keys->mki_id = NULL; } + srtp_crypto_free(session_keys); + } /* deallocate key usage limit, if it is not the same as that in template */ From 04eeef806d45d218fbb40ca3d831f79534ca8947 Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Tue, 31 Jan 2017 15:45:12 -0500 Subject: [PATCH 06/10] Updating code base off of code review comments --- srtp/srtp.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/srtp/srtp.c b/srtp/srtp.c index 5896a5acd..932221703 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -224,6 +224,7 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, } str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); + memset(str->session_keys, 0, sizeof(srtp_session_keys_t) * str->num_master_keys); for (i = 0; i < str->num_master_keys; i++) { session_keys = &str->session_keys[i]; @@ -431,10 +432,16 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat session_keys->mki_id = NULL; } - srtp_crypto_free(session_keys); + } + if (stream_template + && stream->session_keys == stream_template->session_keys) { + /* do nothing */ + } else { + srtp_crypto_free(stream->session_keys); } + /* deallocate key usage limit, if it is not the same as that in template */ if (stream_template && stream->limit == stream_template->limit) { @@ -2204,7 +2211,7 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned #endif /* - * Determine if MKI is being used and what the MKI index is + * Determine if MKI is being used and what session keys should be used */ if (use_mki) { session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, (const unsigned int*)pkt_octet_len, &mki_size); @@ -3787,7 +3794,7 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne } /* - * Determine if MKI is being used and what the MKI index is + * Determine if MKI is being used and what session keys should be used */ if (use_mki) { session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, (const unsigned int*)pkt_octet_len, &mki_size); @@ -3856,9 +3863,9 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne auth_start = (uint32_t *)hdr; /* - * The location of the auth tag in the packet needs to know MKI ID + * The location of the auth tag in the packet needs to know MKI * could be present. The data needed to calculate the Auth tag - * must not include the MKI ID + * must not include the MKI */ auth_len = *pkt_octet_len - tag_len - mki_size; auth_tag = (uint8_t *)hdr + auth_len + mki_size; From f38d8937cfd52e12489c48e543aabb6f182acccd Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Tue, 31 Jan 2017 16:11:54 -0500 Subject: [PATCH 07/10] Moving the key limit structure to part of the Session Keys --- include/srtp_priv.h | 2 +- srtp/srtp.c | 83 +++++++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/include/srtp_priv.h b/include/srtp_priv.h index 8e8576e56..6b4d2bdd0 100644 --- a/include/srtp_priv.h +++ b/include/srtp_priv.h @@ -122,6 +122,7 @@ typedef struct srtp_session_keys_t { uint8_t c_salt[SRTP_AEAD_SALT_LEN]; uint8_t *mki_id; unsigned int mki_size; + srtp_key_limit_ctx_t *limit; } srtp_session_keys_t; @@ -141,7 +142,6 @@ typedef struct srtp_stream_ctx_t_ { srtp_sec_serv_t rtp_services; srtp_rdb_t rtcp_rdb; srtp_sec_serv_t rtcp_services; - srtp_key_limit_ctx_t *limit; direction_t direction; int allow_repeat_tx; srtp_ekt_stream_t ekt; diff --git a/srtp/srtp.c b/srtp/srtp.c index 932221703..aef9ab839 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -176,6 +176,10 @@ srtp_stream_free(srtp_stream_ctx_t *str) { if (session_keys->mki_id) { srtp_crypto_free(session_keys->mki_id); } + + if (session_keys->limit) { + srtp_crypto_free(session_keys->limit); + } } srtp_crypto_free(str->session_keys); @@ -183,9 +187,6 @@ srtp_stream_free(srtp_stream_ctx_t *str) { if (str->enc_xtn_hdr) { srtp_crypto_free(str->enc_xtn_hdr); } - if (str->limit) { - srtp_crypto_free(str->limit); - } srtp_crypto_free(str); } @@ -274,13 +275,12 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, session_keys->mki_id = NULL; - } - - /* allocate key limit structure */ - str->limit = (srtp_key_limit_ctx_t*) srtp_crypto_alloc(sizeof(srtp_key_limit_ctx_t)); - if (str->limit == NULL) { - srtp_stream_free(str); - return srtp_err_status_alloc_fail; + /* allocate key limit structure */ + 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); + return srtp_err_status_alloc_fail; + } } /* allocate ekt data associated with stream */ @@ -432,6 +432,14 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat 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 @@ -441,15 +449,6 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat srtp_crypto_free(stream->session_keys); } - - /* deallocate key usage limit, if it is not the same as that in template */ - if (stream_template - && stream->limit == stream_template->limit) { - /* do nothing */ - } else { - srtp_crypto_free(stream->limit); - } - status = srtp_rdbx_dealloc(&stream->rtp_rdbx); if (status) return status; @@ -525,16 +524,17 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, /* Copy the salt values */ memcpy(session_keys->salt, template_session_keys->salt, SRTP_AEAD_SALT_LEN); memcpy(session_keys->c_salt, template_session_keys->c_salt, SRTP_AEAD_SALT_LEN); - } - /* set key limit to point to that of the template */ - status = srtp_key_limit_clone(stream_template->limit, &str->limit); - if (status) { - srtp_crypto_free(*str_ptr); - *str_ptr = NULL; - return status; + /* set key limit to point to that of the template */ + status = srtp_key_limit_clone(template_session_keys->limit, &session_keys->limit); + if (status) { + srtp_crypto_free(*str_ptr); + *str_ptr = NULL; + return status; + } } + /* initialize replay databases */ status = srtp_rdbx_init(&str->rtp_rdbx, srtp_rdbx_get_window_size(&stream_template->rtp_rdbx)); @@ -854,6 +854,18 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, co * be part of srtp_policy_t. */ session_keys = &srtp->session_keys[current_mki_index]; + /* initialize key limit to maximum value */ +#ifdef NO_64BIT_MATH +{ + uint64_t temp; + temp = make64(UINT_MAX,UINT_MAX); + srtp_key_limit_set(session_keys->limit, temp); +} +#else + srtp_key_limit_set(session_keys->limit, 0xffffffffffffLL); +#endif + + if ( master_key->mki_size != 0 ) { session_keys->mki_id = srtp_crypto_alloc(master_key->mki_size); @@ -1154,17 +1166,6 @@ srtp_stream_init(srtp_stream_ctx_t *srtp, err = srtp_rdbx_init(&srtp->rtp_rdbx, 128); if (err) return err; - /* initialize key limit to maximum value */ -#ifdef NO_64BIT_MATH -{ - uint64_t temp; - temp = make64(UINT_MAX,UINT_MAX); - srtp_key_limit_set(srtp->limit, temp); -} -#else - srtp_key_limit_set(srtp->limit, 0xffffffffffffLL); -#endif - /* set the SSRC value */ srtp->ssrc = htonl(p->ssrc.value); @@ -1515,7 +1516,7 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, * didn't just hit either the soft limit or the hard limit, and call * the event handler if we hit either. */ - switch (srtp_key_limit_update(stream->limit)) { + switch (srtp_key_limit_update(session_keys->limit)) { case srtp_key_event_normal: break; case srtp_key_event_hard_limit: @@ -1726,7 +1727,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * didn't just hit either the soft limit or the hard limit, and call * the event handler if we hit either. */ - switch (srtp_key_limit_update(stream->limit)) { + switch (srtp_key_limit_update(session_keys->limit)) { case srtp_key_event_normal: break; case srtp_key_event_soft_limit: @@ -1927,7 +1928,7 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * didn't just hit either the soft limit or the hard limit, and call * the event handler if we hit either. */ - switch(srtp_key_limit_update(stream->limit)) { + switch(srtp_key_limit_update(session_keys->limit)) { case srtp_key_event_normal: break; case srtp_key_event_soft_limit: @@ -2366,7 +2367,7 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned * didn't just hit either the soft limit or the hard limit, and call * the event handler if we hit either. */ - switch(srtp_key_limit_update(stream->limit)) { + switch(srtp_key_limit_update(session_keys->limit)) { case srtp_key_event_normal: break; case srtp_key_event_soft_limit: From ab0345b241133e894a326136b4b2a3b1f7e70e74 Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Tue, 7 Feb 2017 16:07:59 -0500 Subject: [PATCH 08/10] Updated the srtp function to get the protected length added by LibSRTP via code review comments --- include/srtp.h | 35 +++++--- srtp/srtp.c | 74 +++++++++++++--- test/srtp_driver.c | 213 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+), 22 deletions(-) diff --git a/include/srtp.h b/include/srtp.h index 3f1f59e7a..fde2f5d63 100644 --- a/include/srtp.h +++ b/include/srtp.h @@ -78,15 +78,22 @@ extern "C" { #define SRTP_MAX_TAG_LEN 16 +/** + * SRTP_MAX_MKI_LEN is the maximum size the MKI could be which is + * 128 bytes + */ +#define SRTP_MAX_MKI_LEN 128 + + /** * SRTP_MAX_TRAILER_LEN is the maximum length of the SRTP trailer * (authentication tag and MKI) supported by libSRTP. This value is - * the maximum number of octets that will be added to an RTP packet by + * the maixmum number of octets that will be added to an RTP packet by * srtp_protect(). * * @brief the maximum number of octets added by srtp_protect(). */ -#define SRTP_MAX_TRAILER_LEN SRTP_MAX_TAG_LEN +#define SRTP_MAX_TRAILER_LEN SRTP_MAX_TAG_LEN + SRTP_MAX_MKI_LEN /** * SRTP_MAX_NUM_MASTER_KEYS is the maximum number of Master keys for @@ -95,12 +102,6 @@ extern "C" { */ #define SRTP_MAX_NUM_MASTER_KEYS 16 -/** - * SRTP_MAX_MKI_LEN is the maximum size the MKI could be which is - * 128 bytes - */ -#define SRTP_MAX_MKI_LEN 128 - /* * SRTP_AEAD_SALT_LEN is the length of the SALT values used with * GCM mode. GCM mode requires an IV. The SALT value is used @@ -1698,7 +1699,19 @@ srtp_err_status_t srtp_set_debug_module(char *mod_name, int v); srtp_err_status_t srtp_list_debug_modules(void); /** - * @brief srtp_get_protect_data_added_length(policy, use_mki, mki_index, is_rtcp, length) + * @brief srtp_get_protect_trailer_length(session, use_mki, mki_index, length) + * + * Determines the length of the amount of data Lib SRTP will add to the + * packet during the protect process. The length is returned in the length parameter + * + * returns err_status_ok on success, err_status_bad_mki if the MKI index is invalid + * + */ +srtp_err_status_t srtp_get_protect_trailer_length(srtp_t session, uint32_t use_mki, + uint32_t mki_index, uint32_t *length); + +/** + * @brief srtp_get_protect_rtcp_trailer_length(session, use_mki, mki_index, length) * * Determines the length of the amount of data Lib SRTP will add to the * packet during the protect process. The length is returned in the length parameter @@ -1706,8 +1719,8 @@ srtp_err_status_t srtp_list_debug_modules(void); * returns err_status_ok on success, err_status_bad_mki if the MKI index is invalid * */ -srtp_err_status_t srtp_get_protect_data_added_length(const srtp_policy_t *policy, uint32_t use_mki, - uint32_t mki_index, uint32_t is_rtcp, uint32_t *length); +srtp_err_status_t srtp_get_protect_rtcp_trailer_length(srtp_t session, uint32_t use_mki, + uint32_t mki_index, uint32_t *length); /** diff --git a/srtp/srtp.c b/srtp/srtp.c index 0d55d8120..1c5b5c2b9 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -4163,27 +4163,79 @@ srtp_profile_get_master_salt_length(srtp_profile_t profile) { } srtp_err_status_t -srtp_get_protect_data_added_length(const srtp_policy_t *policy, - uint32_t use_mki, - uint32_t mki_index, - uint32_t is_rtcp, - uint32_t *length) +srtp_get_protect_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length) { + srtp_stream_ctx_t *stream; + + if (session == NULL) + return srtp_err_status_bad_param; + *length = 0; + /* Try obtaining stream from stream_list */ + stream = session->stream_list; + + if (stream == NULL) { + /* Try obtaining the template stream */ + stream = session->stream_template; + } + + if (stream == NULL) { + return srtp_err_status_bad_param; + } + if (use_mki) { - if (mki_index > policy->num_master_keys) + if (mki_index > stream->num_master_keys) return srtp_err_status_bad_mki; - *length += policy->keys[mki_index]->mki_size; + *length += stream->session_keys[mki_index].mki_size; + *length += srtp_auth_get_tag_length(stream->session_keys[mki_index].rtp_auth); + } else { + *length += srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth); + } + + return srtp_err_status_ok; +} + +srtp_err_status_t +srtp_get_protect_rtcp_trailer_length(srtp_t session, + uint32_t use_mki, + uint32_t mki_index, + uint32_t *length) +{ + srtp_stream_ctx_t *stream; + + if (session == NULL) + return srtp_err_status_bad_param; + + *length = 0; + + /* Try obtaining stream from stream_list */ + stream = session->stream_list; + + if (stream == NULL) { + /* Try obtaining the template stream */ + stream = session->stream_template; + } + + if (stream == NULL) { + return srtp_err_status_bad_param; } - if (is_rtcp) { - *length += sizeof(srtcp_trailer_t); - *length += policy->rtcp.auth_tag_len; + if (use_mki) { + if (mki_index > stream->num_master_keys) + return srtp_err_status_bad_mki; + + *length += stream->session_keys[mki_index].mki_size; + *length += srtp_auth_get_tag_length(stream->session_keys[mki_index].rtcp_auth); } else { - *length += policy->rtp.auth_tag_len; + *length += srtp_auth_get_tag_length(stream->session_keys[0].rtcp_auth); } + + *length += sizeof(srtcp_trailer_t); return srtp_err_status_ok; } diff --git a/test/srtp_driver.c b/test/srtp_driver.c index e801f821a..ab521ebb0 100644 --- a/test/srtp_driver.c +++ b/test/srtp_driver.c @@ -1,4 +1,5 @@ + /* * srtp_driver.c * @@ -101,6 +102,12 @@ srtp_test_remove_stream(void); srtp_err_status_t srtp_test_update(void); +srtp_err_status_t +srtp_test_protect_trailer_length(void); + +srtp_err_status_t +srtp_test_protect_rtcp_trailer_length(void); + double srtp_bits_per_second(int msg_len_octets, const srtp_policy_t *policy); @@ -480,6 +487,26 @@ main (int argc, char *argv[]) printf("failed\n"); exit(1); } + + /* + * test the functions srtp_get_protect_trailer_length + * and srtp_get_protect_rtcp_trailer_length + */ + printf("testing srtp_get_protect_trailer_length()..."); + if (srtp_test_protect_trailer_length() == srtp_err_status_ok) { + printf("passed\n"); + } else { + printf("failed\n"); + exit(1); + } + + printf("testing srtp_get_protect_rtcp_trailer_length()..."); + if (srtp_test_protect_rtcp_trailer_length() == srtp_err_status_ok) { + printf("passed\n"); + } else { + printf("failed\n"); + exit(1); + } } if (do_timing_test) { @@ -2720,6 +2747,192 @@ srtp_test_update() { return srtp_err_status_ok; } +srtp_err_status_t +srtp_test_setup_protect_trailer_streams(srtp_t *srtp_send, srtp_t *srtp_send_mki, + srtp_t *srtp_send_aes_gcm, srtp_t *srtp_send_aes_gcm_mki) { + + srtp_err_status_t status; + srtp_policy_t policy; + srtp_policy_t policy_mki; +#ifdef OPENSSL + srtp_policy_t policy_aes_gcm; + srtp_policy_t policy_aes_gcm_mki; +#endif // OPENSSL + + memset(&policy, 0, sizeof(policy)); + srtp_crypto_policy_set_rtp_default(&policy.rtp); + srtp_crypto_policy_set_rtcp_default(&policy.rtcp); + policy.ekt = NULL; + policy.window_size = 128; + policy.allow_repeat_tx = 0; + policy.next = NULL; + policy.ssrc.type = ssrc_any_outbound; + policy.key = test_key; + + memset(&policy_mki, 0, sizeof(policy_mki)); + srtp_crypto_policy_set_rtp_default(&policy_mki.rtp); + srtp_crypto_policy_set_rtcp_default(&policy_mki.rtcp); + policy_mki.ekt = NULL; + policy_mki.window_size = 128; + policy_mki.allow_repeat_tx = 0; + policy_mki.next = NULL; + policy_mki.ssrc.type = ssrc_any_outbound; + policy_mki.key = NULL; + policy_mki.keys = test_keys; + policy_mki.num_master_keys = 2; + +#ifdef OPENSSL + memset(&policy_aes_gcm, 0, sizeof(policy_aes_gcm)); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm.rtcp); + policy_aes_gcm.ekt = NULL; + policy_aes_gcm.window_size = 128; + policy_aes_gcm.allow_repeat_tx = 0; + policy_aes_gcm.next = NULL; + policy_aes_gcm.ssrc.type = ssrc_any_outbound; + policy_aes_gcm.key = test_key; + + memset(&policy_aes_gcm_mki, 0, sizeof(policy_aes_gcm_mki)); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtp); + srtp_crypto_policy_set_aes_gcm_128_16_auth(&policy_aes_gcm_mki.rtcp); + policy_aes_gcm_mki.ekt = NULL; + policy_aes_gcm_mki.window_size = 128; + policy_aes_gcm_mki.allow_repeat_tx = 0; + policy_aes_gcm_mki.next = NULL; + policy_aes_gcm_mki.ssrc.type = ssrc_any_outbound; + policy_aes_gcm_mki.key = NULL; + policy_aes_gcm_mki.keys = test_keys; + policy_aes_gcm_mki.num_master_keys = 2; + +#endif + + /* create a send ctx with defualt profile and test_key */ + status = srtp_create(srtp_send, &policy); + if (status) + return status; + + status = srtp_create(srtp_send_mki, &policy_mki); + if (status) + return status; + +#ifdef OPENSSL + status = srtp_create(srtp_send_aes_gcm, &policy_aes_gcm); + if (status) + return status; + + status = srtp_create(srtp_send_aes_gcm_mki, &policy_aes_gcm_mki); + if (status) + return status; +#endif //OPENSSL + + return srtp_err_status_ok; +} + +srtp_err_status_t +srtp_test_protect_trailer_length() { + + srtp_t srtp_send; + srtp_t srtp_send_mki; + srtp_t srtp_send_aes_gcm; + srtp_t srtp_send_aes_gcm_mki; + uint32_t length = 0; + srtp_err_status_t status; + + srtp_test_setup_protect_trailer_streams(&srtp_send, &srtp_send_mki, + &srtp_send_aes_gcm, &srtp_send_aes_gcm_mki); + + status = srtp_get_protect_trailer_length(srtp_send, 0, 0, &length); + if (status) + return status; + + /* TAG Length: 10 bytes */ + if (length != 10) + return srtp_err_status_fail; + + status = srtp_get_protect_trailer_length(srtp_send_mki, 1, 1, &length); + if (status) + return status; + + /* TAG Length: 10 bytes + MKI length: 4 bytes*/ + if (length != 14) + return srtp_err_status_fail; + +#ifdef OPENSSL + status = srtp_get_protect_trailer_length(srtp_send_aes_gcm, 0, 0, &length); + if (status) + return status; + + /* TAG Length: 16 bytes */ + if (length != 16) + return srtp_err_status_fail; + + + status = srtp_get_protect_trailer_length(srtp_send_aes_gcm_mki, 1, 1, &length); + if (status) + return status; + + /* TAG Length: 16 bytes + MKI length: 4 bytes*/ + if (length != 20) + return srtp_err_status_fail; + +#endif //OPENSSL + + return srtp_err_status_ok; +} + +srtp_err_status_t +srtp_test_protect_rtcp_trailer_length() { + + srtp_t srtp_send; + srtp_t srtp_send_mki; + srtp_t srtp_send_aes_gcm; + srtp_t srtp_send_aes_gcm_mki; + uint32_t length = 0; + srtp_err_status_t status; + + srtp_test_setup_protect_trailer_streams(&srtp_send, &srtp_send_mki, + &srtp_send_aes_gcm, &srtp_send_aes_gcm_mki); + + status = srtp_get_protect_rtcp_trailer_length(srtp_send, 0, 0, &length); + if (status) + return status; + + /* TAG Length: 10 bytes + SRTCP Trailer 4 bytes*/ + if (length != 14) + return srtp_err_status_fail; + + status = srtp_get_protect_rtcp_trailer_length(srtp_send_mki, 1, 1, &length); + if (status) + return status; + + /* TAG Length: 10 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ + if (length != 18) + return srtp_err_status_fail; + +#ifdef OPENSSL + status = srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm, 0, 0, &length); + if (status) + return status; + + /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes*/ + if (length != 20) + return srtp_err_status_fail; + + + status = srtp_get_protect_rtcp_trailer_length(srtp_send_aes_gcm_mki, 1, 1, &length); + if (status) + return status; + + /* TAG Length: 16 bytes + SRTCP Trailer 4 bytes + MKI 4 bytes*/ + if (length != 24) + return srtp_err_status_fail; + +#endif //OPENSSL + + return srtp_err_status_ok; +} + + /* * srtp policy definitions - these definitions are used above */ From 5cd58c0f7f9fe331df4061d7519372c2a1bbe656 Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Wed, 8 Feb 2017 15:28:56 -0500 Subject: [PATCH 09/10] Addressing code review comments --- srtp/srtp.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/srtp/srtp.c b/srtp/srtp.c index 1c5b5c2b9..3382600ed 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -225,6 +225,12 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, } str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); + + if (str->session_keys == NULL) { + srtp_stream_free(str); + return srtp_err_status_alloc_fail; + } + memset(str->session_keys, 0, sizeof(srtp_session_keys_t) * str->num_master_keys); for (i = 0; i < str->num_master_keys; i++) { @@ -423,11 +429,11 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat /* * zeroize the salt value */ - memset(session_keys->salt, 0, SRTP_AEAD_SALT_LEN); - memset(session_keys->c_salt, 0, SRTP_AEAD_SALT_LEN); + 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) { - memset(session_keys->mki_id, 0, session_keys->mki_size); + 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; } @@ -498,6 +504,12 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, str->num_master_keys = stream_template->num_master_keys; str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); + if (str->session_keys == NULL) { + srtp_crypto_free(*str_ptr); + *str_ptr = NULL; + return srtp_err_status_alloc_fail; + } + for (i = 0; i < stream_template->num_master_keys; i++){ session_keys = &str->session_keys[i]; template_session_keys = &stream_template->session_keys[i]; @@ -1467,6 +1479,11 @@ srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, const unsigned in tag_len = srtp_auth_get_tag_length(stream->session_keys[0].rtp_auth); } + if (tag_len > base_mki_start_location) { + *mki_size = 0; + return NULL; + } + base_mki_start_location -= tag_len; for (i = 0; i < stream->num_master_keys; i++) { From 626e9e8431795fecc33b77b33cf46efd9cad8fbd Mon Sep 17 00:00:00 2001 From: Geir Istad Date: Mon, 20 Feb 2017 18:15:05 +0100 Subject: [PATCH 10/10] Apply some formatting nits Core of this is to limit the line length to at least 90 width where it makes sense contextually. Some whitespace fixups were applied as well, mainly replacing tabs with spaces since this seems like the most consistently used white space. This was done around points where this PR is touching the repo in order to improve the readability slightly. --- include/srtp.h | 15 ++- include/srtp_priv.h | 9 +- srtp/srtp.c | 283 ++++++++++++++++++++++++++------------------ 3 files changed, 182 insertions(+), 125 deletions(-) diff --git a/include/srtp.h b/include/srtp.h index fde2f5d63..9b9392964 100644 --- a/include/srtp.h +++ b/include/srtp.h @@ -588,9 +588,10 @@ srtp_err_status_t srtp_protect(srtp_t ctx, void *rtp_hdr, int *len_ptr); * - @e other failure in cryptographic mechanisms */ -srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len, - unsigned int use_mki, unsigned int mki_index); - +srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, + int *pkt_octet_len, unsigned int use_mki, + unsigned int mki_index); + /** * @brief srtp_unprotect() is the Secure RTP receiver-side packet * processing function. @@ -676,7 +677,8 @@ srtp_err_status_t srtp_unprotect(srtp_t ctx, void *srtp_hdr, int *len_ptr); * */ - srtp_err_status_t srtp_unprotect_mki(srtp_t ctx, void *srtp_hdr, int *len_ptr, unsigned int use_mki); +srtp_err_status_t srtp_unprotect_mki(srtp_t ctx, void *srtp_hdr, int *len_ptr, + unsigned int use_mki); /** * @brief srtp_create() allocates and initializes an SRTP session. @@ -1513,8 +1515,9 @@ srtp_err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octe * */ -srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigned int use_mki); - +srtp_err_status_t srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, + int *pkt_octet_len, + unsigned int use_mki); /** * @} diff --git a/include/srtp_priv.h b/include/srtp_priv.h index 6b4d2bdd0..ef4d01ca7 100644 --- a/include/srtp_priv.h +++ b/include/srtp_priv.h @@ -78,16 +78,17 @@ srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc); * srtp_stream_init_keys(s, k) (re)initializes the srtp_stream_t s by * deriving all of the needed keys using the KDF and the key k. */ -srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, const unsigned int current_mki_index); - +srtp_err_status_t srtp_stream_init_keys(srtp_stream_ctx_t *srtp, + srtp_master_key_t *master_key, + const unsigned int current_mki_index); /* * srtp_stream_init_all_master_keys(s, k, m) (re)initializes the srtp_stream_t s by * deriving all of the needed keys for all the master keys using the KDF and the keys from k. */ srtp_err_status_t srtp_steam_init_all_master_keys(srtp_stream_ctx_t *srtp, - unsigned char *key, - srtp_master_key_t **keys, + unsigned char *key, + srtp_master_key_t **keys, const unsigned int max_master_keys); /* diff --git a/srtp/srtp.c b/srtp/srtp.c index 3382600ed..56b225a1e 100644 --- a/srtp/srtp.c +++ b/srtp/srtp.c @@ -224,7 +224,8 @@ srtp_stream_alloc(srtp_stream_ctx_t **str_ptr, str->num_master_keys = p->num_master_keys; } - str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( + sizeof(srtp_session_keys_t) * str->num_master_keys); if (str->session_keys == NULL) { srtp_stream_free(str); @@ -373,7 +374,7 @@ srtp_stream_dealloc(srtp_stream_ctx_t *stream, srtp_stream_ctx_t *stream_templat /* 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) { + && session_keys->rtp_cipher == template_session_keys->rtp_cipher) { /* do nothing */ } else { status = srtp_cipher_dealloc(session_keys->rtp_cipher); @@ -502,7 +503,8 @@ srtp_stream_clone(const srtp_stream_ctx_t *stream_template, *str_ptr = str; str->num_master_keys = stream_template->num_master_keys; - str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(sizeof(srtp_session_keys_t) * str->num_master_keys); + str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc( + sizeof(srtp_session_keys_t) * str->num_master_keys); if (str->session_keys == NULL) { srtp_crypto_free(*str_ptr); @@ -791,8 +793,9 @@ srtp_validate_policy_master_keys(const srtp_policy_t *policy) } srtp_session_keys_t* -srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t *stream, unsigned int use_mki, unsigned int mki_index) -{ +srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t *stream, + unsigned int use_mki, + unsigned int mki_index) { if (use_mki) { if (mki_index < stream->num_master_keys) { return &stream->session_keys[mki_index]; @@ -803,7 +806,8 @@ srtp_get_session_keys_with_mki_index(srtp_stream_ctx_t *stream, unsigned int use } unsigned int -srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, unsigned int use_mki) +srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, + unsigned int use_mki) { unsigned int mki_size = 0; @@ -821,9 +825,9 @@ srtp_inject_mki(uint8_t *mki_tag_location, srtp_session_keys_t* session_keys, un srtp_err_status_t srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, - unsigned char *key, - srtp_master_key_t **keys, - const unsigned int max_master_keys) { + unsigned char *key, + srtp_master_key_t **keys, + const unsigned int max_master_keys) { int i = 0; srtp_err_status_t status = srtp_err_status_ok; srtp_master_key_t single_master_key; @@ -850,7 +854,8 @@ srtp_stream_init_all_master_keys(srtp_stream_ctx_t *srtp, } srtp_err_status_t -srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, const unsigned int current_mki_index) { +srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, + const unsigned int current_mki_index) { srtp_err_status_t stat; srtp_kdf_t kdf; uint8_t tmp_key[MAX_SRTP_KEY_LEN]; @@ -982,7 +987,8 @@ srtp_stream_init_keys(srtp_stream_ctx_t *srtp, srtp_master_key_t *master_key, co /* See https://tools.ietf.org/html/draft-ietf-avtcore-srtp-aes-gcm-17#section-8.3 */ uint8_t tmp_xtn_hdr_key[MAX_SRTP_KEY_LEN]; rtp_xtn_hdr_keylen = srtp_cipher_get_key_length(session_keys->rtp_xtn_hdr_cipher); - rtp_xtn_hdr_base_key_len = base_key_length(session_keys->rtp_xtn_hdr_cipher->type, rtp_xtn_hdr_keylen); + rtp_xtn_hdr_base_key_len = base_key_length(session_keys->rtp_xtn_hdr_cipher->type, + rtp_xtn_hdr_keylen); rtp_xtn_hdr_salt_len = rtp_xtn_hdr_keylen - rtp_xtn_hdr_base_key_len; memset(tmp_xtn_hdr_key, 0x0, MAX_SRTP_KEY_LEN); memcpy(tmp_xtn_hdr_key, key, (rtp_xtn_hdr_base_key_len + rtp_xtn_hdr_salt_len)); @@ -1310,7 +1316,9 @@ srtp_protect_extension_header(srtp_stream_ctx_t *stream, int id) { * extensions header encryption RFC 6904 */ static srtp_err_status_t -srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_hdr, srtp_session_keys_t *session_keys) { +srtp_process_header_encryption(srtp_stream_ctx_t *stream, + srtp_hdr_xtnd_t *xtn_hdr, + srtp_session_keys_t *session_keys) { srtp_err_status_t status; uint8_t keystream[257]; /* Maximum 2 bytes header + 255 bytes data. */ int keystream_pos; @@ -1333,7 +1341,8 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_h break; } - status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, keystream, &xlen_with_header); + status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, + keystream, &xlen_with_header); if (status) return srtp_err_status_cipher_fail; @@ -1364,7 +1373,8 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_h if (xtn_hdr_data + xlen > xtn_hdr_end) return srtp_err_status_parse_err; - status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, keystream, &xlen_with_header); + status = srtp_cipher_output(session_keys->rtp_xtn_hdr_cipher, + keystream, &xlen_with_header); if (status) return srtp_err_status_cipher_fail; @@ -1423,7 +1433,7 @@ srtp_process_header_encryption(srtp_stream_ctx_t *stream, srtp_hdr_xtnd_t *xtn_h */ static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys, v128_t *iv, - srtp_xtd_seq_num_t *seq, srtp_hdr_t *hdr) + srtp_xtd_seq_num_t *seq, srtp_hdr_t *hdr) { v128_t in; v128_t salt; @@ -1464,8 +1474,9 @@ static void srtp_calc_aead_iv(srtp_session_keys_t *session_keys, v128_t *iv, srtp_session_keys_t* -srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, const unsigned int* pkt_octet_len, unsigned int* mki_size) { - +srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, + const unsigned int* pkt_octet_len, + unsigned int* mki_size) { unsigned int base_mki_start_location = *pkt_octet_len; unsigned int mki_start_location = 0; unsigned int tag_len = 0; @@ -1508,8 +1519,8 @@ srtp_get_session_keys(srtp_stream_ctx_t *stream, uint8_t* hdr, const unsigned in * encrypted and authenticated. */ static srtp_err_status_t -srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, - void *rtp_hdr, unsigned int *pkt_octet_len, +srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, + void *rtp_hdr, unsigned int *pkt_octet_len, srtp_session_keys_t *session_keys, unsigned int use_mki) { srtp_hdr_t *hdr = (srtp_hdr_t*)rtp_hdr; @@ -1599,12 +1610,14 @@ srtp_protect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, est = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, + (uint8_t*)&iv, srtp_direction_encrypt); if (!status && session_keys->rtp_xtn_hdr_cipher) { iv.v32[0] = 0; iv.v32[1] = hdr->ssrc; iv.v64[1] = est; - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t*)&iv, srtp_direction_encrypt); } if (status) { return srtp_err_status_cipher_fail; @@ -1694,7 +1707,8 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, * AEAD uses a new IV formation method */ srtp_calc_aead_iv(session_keys, &iv, &est, hdr); - status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, + (uint8_t*)&iv, srtp_direction_decrypt); if (!status && session_keys->rtp_xtn_hdr_cipher) { iv.v32[0] = 0; iv.v32[1] = hdr->ssrc; @@ -1767,7 +1781,8 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, /* Decrypt the ciphertext. This also checks the auth tag based * on the AAD we just specified above */ - status = srtp_cipher_decrypt(session_keys->rtp_cipher, (uint8_t*)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtp_cipher, + (uint8_t*)enc_start, &enc_octet_len); if (status) { return status; } @@ -1849,8 +1864,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, return srtp_protect_mki(ctx, rtp_hdr, pkt_octet_len, 0, 0); } - srtp_err_status_t - srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len, unsigned int use_mki, unsigned int mki_index ) { +srtp_err_status_t +srtp_protect_mki(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len, + unsigned int use_mki, unsigned int mki_index ) { srtp_hdr_t *hdr = (srtp_hdr_t *)rtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -1936,7 +1952,9 @@ srtp_unprotect_aead (srtp_ctx_t *ctx, srtp_stream_ctx_t *stream, int delta, */ if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_protect_aead(ctx, stream, rtp_hdr, (unsigned int*)pkt_octet_len, session_keys, use_mki); + return srtp_protect_aead(ctx, stream, rtp_hdr, + (unsigned int*)pkt_octet_len, session_keys, + use_mki); } /* @@ -2147,7 +2165,8 @@ srtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) { } srtp_err_status_t -srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned int use_mki) { +srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, + unsigned int use_mki) { srtp_hdr_t *hdr = (srtp_hdr_t *)srtp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -2231,7 +2250,9 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned * Determine if MKI is being used and what session keys should be used */ if (use_mki) { - session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, (const unsigned int*)pkt_octet_len, &mki_size); + session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, + (const unsigned int*)pkt_octet_len, + &mki_size); if (session_keys == NULL) return srtp_err_status_bad_mki; @@ -2245,7 +2266,9 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned */ if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, (unsigned int*)pkt_octet_len, session_keys, mki_size); + return srtp_unprotect_aead(ctx, stream, delta, est, srtp_hdr, + (unsigned int*)pkt_octet_len, session_keys, + mki_size); } /* get tag length from stream */ @@ -2267,9 +2290,11 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned #else iv.v64[1] = be64_to_cpu(est << 16); #endif - status = srtp_cipher_set_iv(session_keys->rtp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtp_cipher, + (uint8_t*)&iv, srtp_direction_decrypt); if (!status && session_keys->rtp_xtn_hdr_cipher) { - status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtp_xtn_hdr_cipher, + (uint8_t*)&iv, srtp_direction_decrypt); } } else { @@ -2408,7 +2433,8 @@ srtp_unprotect_mki(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len, unsigned /* if we're decrypting, add keystream into ciphertext */ if (enc_start) { - status = srtp_cipher_decrypt(session_keys->rtp_cipher, (uint8_t *)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtp_cipher, + (uint8_t *)enc_start, &enc_octet_len); if (status) return srtp_err_status_cipher_fail; } @@ -2770,7 +2796,9 @@ update_template_streams(srtp_t session, const srtp_policy_t *policy) { srtp_rdb_t old_rtcp_rdb; stream = session->stream_list; - while ((stream != NULL) && (stream->session_keys[0].rtp_auth != session->stream_template->session_keys[0].rtp_auth)) { + while ((stream != NULL) && + (stream->session_keys[0].rtp_auth != + session->stream_template->session_keys[0].rtp_auth)) { stream = stream->next; } if (stream == NULL) { @@ -3238,7 +3266,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, *trailer = 0x00000000; /* set encrypt bit */ } - mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len + sizeof(srtcp_trailer_t), session_keys, use_mki); + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + tag_len + sizeof(srtcp_trailer_t), + session_keys, use_mki); /* * set the auth_tag pointer to the proper location, which is after @@ -3264,7 +3293,8 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Calculating the IV and pass it down to the cipher */ srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, + (uint8_t*)&iv, srtp_direction_encrypt); if (status) { return srtp_err_status_cipher_fail; } @@ -3273,30 +3303,33 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Set the AAD for GCM mode */ if (enc_start) { - /* - * If payload encryption is enabled, then the AAD consist of - * the RTCP header and the seq# at the end of the packet - */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, octets_in_rtcp_header); - if (status) { - return ( srtp_err_status_cipher_fail); - } + /* + * If payload encryption is enabled, then the AAD consist of + * the RTCP header and the seq# at the end of the packet + */ + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, + (uint8_t*)hdr, octets_in_rtcp_header); + if (status) { + return ( srtp_err_status_cipher_fail); + } } else { - /* - * Since payload encryption is not enabled, we must authenticate - * the entire packet as described in section 10.3 in revision 07 - * of the draft. - */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, *pkt_octet_len); - if (status) { - return ( srtp_err_status_cipher_fail); - } + /* + * Since payload encryption is not enabled, we must authenticate + * the entire packet as described in section 10.3 in revision 07 + * of the draft. + */ + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, + (uint8_t*)hdr, *pkt_octet_len); + if (status) { + return ( srtp_err_status_cipher_fail); + } } - /* + /* * Process the sequence# as AAD */ tseq = *trailer; - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)&tseq, + sizeof(srtcp_trailer_t)); if (status) { return ( srtp_err_status_cipher_fail); } @@ -3304,36 +3337,38 @@ srtp_protect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, /* if we're encrypting, exor keystream into the message */ if (enc_start) { status = srtp_cipher_encrypt(session_keys->rtcp_cipher, - (uint8_t*)enc_start, &enc_octet_len); + (uint8_t*)enc_start, &enc_octet_len); if (status) { return srtp_err_status_cipher_fail; } - /* - * Get the tag and append that to the output - */ - status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tag_len); - if (status) { - return ( srtp_err_status_cipher_fail); - } - enc_octet_len += tag_len; + /* + * Get the tag and append that to the output + */ + status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, + &tag_len); + if (status) { + return ( srtp_err_status_cipher_fail); + } + enc_octet_len += tag_len; } else { - /* - * Even though we're not encrypting the payload, we need - * to run the cipher to get the auth tag. - */ - unsigned int nolen = 0; + /* + * Even though we're not encrypting the payload, we need + * to run the cipher to get the auth tag. + */ + unsigned int nolen = 0; status = srtp_cipher_encrypt(session_keys->rtcp_cipher, NULL, &nolen); if (status) { return srtp_err_status_cipher_fail; } - /* - * Get the tag and append that to the output - */ - status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tag_len); - if (status) { - return ( srtp_err_status_cipher_fail); - } - enc_octet_len += tag_len; + /* + * Get the tag and append that to the output + */ + status = srtp_cipher_get_tag(session_keys->rtcp_cipher, (uint8_t*)auth_tag, + &tag_len); + if (status) { + return ( srtp_err_status_cipher_fail); + } + enc_octet_len += tag_len; } /* increase the packet length by the length of the auth tag and seq_num*/ @@ -3418,7 +3453,8 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Calculate and set the IV */ srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, + (uint8_t*)&iv, srtp_direction_decrypt); if (status) { return srtp_err_status_cipher_fail; } @@ -3427,34 +3463,37 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, * Set the AAD for GCM mode */ if (enc_start) { - /* - * If payload encryption is enabled, then the AAD consist of - * the RTCP header and the seq# at the end of the packet - */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, octets_in_rtcp_header); - if (status) { - return ( srtp_err_status_cipher_fail); - } + /* + * If payload encryption is enabled, then the AAD consist of + * the RTCP header and the seq# at the end of the packet + */ + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, + (uint8_t*)hdr, octets_in_rtcp_header); + if (status) { + return ( srtp_err_status_cipher_fail); + } } else { - /* - * Since payload encryption is not enabled, we must authenticate - * the entire packet as described in section 10.3 in revision 07 - * of the draft. - */ - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)hdr, - (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t) - mki_size)); - if (status) { - return ( srtp_err_status_cipher_fail); - } + /* + * Since payload encryption is not enabled, we must authenticate + * the entire packet as described in section 10.3 in revision 07 + * of the draft. + */ + status = srtp_cipher_set_aad( + session_keys->rtcp_cipher, (uint8_t*)hdr, + (*pkt_octet_len - tag_len - sizeof(srtcp_trailer_t) - mki_size)); + if (status) { + return ( srtp_err_status_cipher_fail); + } } - /* - * Process the sequence# as AAD + /* + * Process the sequence# as AAD */ tseq = *trailer; - status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); + status = srtp_cipher_set_aad(session_keys->rtcp_cipher, + (uint8_t*)&tseq, sizeof(srtcp_trailer_t)); if (status) { - return ( srtp_err_status_cipher_fail); + return ( srtp_err_status_cipher_fail); } /* if we're decrypting, exor keystream into the message */ @@ -3464,10 +3503,10 @@ srtp_unprotect_rtcp_aead (srtp_t ctx, srtp_stream_ctx_t *stream, return status; } } else { - /* - * Still need to run the cipher to check the tag - */ - tmp_len = tag_len; + /* + * Still need to run the cipher to check the tag + */ + tmp_len = tag_len; status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t*)auth_tag, &tmp_len); if (status) { return status; @@ -3535,7 +3574,8 @@ srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { } srtp_err_status_t -srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, unsigned int use_mki, unsigned int mki_index) { +srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, + unsigned int use_mki, unsigned int mki_index) { srtcp_hdr_t *hdr = (srtcp_hdr_t *)rtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -3608,7 +3648,9 @@ srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, unsigned i */ if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, (unsigned int*)pkt_octet_len, session_keys, use_mki); + return srtp_protect_rtcp_aead(ctx, stream, rtcp_hdr, + (unsigned int*)pkt_octet_len, session_keys, + use_mki); } /* get tag length from stream context */ @@ -3637,7 +3679,8 @@ srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, unsigned i *trailer = 0x00000000; /* set encrypt bit */ } - mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t), session_keys, use_mki); + mki_size = srtp_inject_mki((uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t), + session_keys, use_mki); /* * set the auth_start and auth_tag pointers to the proper locations @@ -3672,7 +3715,8 @@ srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, unsigned i iv.v32[1] = hdr->ssrc; /* still in network order! */ iv.v32[2] = htonl(seq_num >> 16); iv.v32[3] = htonl(seq_num << 16); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, + srtp_direction_encrypt); } else { v128_t iv; @@ -3682,7 +3726,8 @@ srtp_protect_rtcp_mki(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len, unsigned i iv.v32[1] = 0; iv.v32[2] = 0; iv.v32[3] = htonl(seq_num); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_encrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, + (uint8_t*)&iv, srtp_direction_encrypt); } if (status) return srtp_err_status_cipher_fail; @@ -3745,8 +3790,9 @@ srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) { return srtp_unprotect_rtcp_mki(ctx, srtcp_hdr, pkt_octet_len, 0); } -srtp_err_status_t -srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigned int use_mki) { +srtp_err_status_t +srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, + unsigned int use_mki) { srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr; uint32_t *enc_start; /* pointer to start of encrypted portion */ uint32_t *auth_start; /* pointer to start of auth. portion */ @@ -3814,7 +3860,9 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne * Determine if MKI is being used and what session keys should be used */ if (use_mki) { - session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, (const unsigned int*)pkt_octet_len, &mki_size); + session_keys = srtp_get_session_keys(stream, (uint8_t *)hdr, + (const unsigned int*)pkt_octet_len, + &mki_size); if (session_keys == NULL) return srtp_err_status_bad_mki; @@ -3839,7 +3887,9 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne */ if (session_keys->rtp_cipher->algorithm == SRTP_AES_128_GCM || session_keys->rtp_cipher->algorithm == SRTP_AES_256_GCM) { - return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr, (unsigned int*)pkt_octet_len, session_keys, mki_size); + return srtp_unprotect_rtcp_aead(ctx, stream, srtcp_hdr, + (unsigned int*)pkt_octet_len, session_keys, + mki_size); } sec_serv_confidentiality = stream->rtcp_services == sec_serv_conf || @@ -3922,7 +3972,8 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne iv.v32[1] = hdr->ssrc; /* still in network order! */ iv.v32[2] = htonl(seq_num >> 16); iv.v32[3] = htonl(seq_num << 16); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, + (uint8_t*)&iv, srtp_direction_decrypt); } else { v128_t iv; @@ -3932,7 +3983,8 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne iv.v32[1] = 0; iv.v32[2] = 0; iv.v32[3] = htonl(seq_num); - status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t*)&iv, srtp_direction_decrypt); + status = srtp_cipher_set_iv(session_keys->rtcp_cipher, + (uint8_t*)&iv, srtp_direction_decrypt); } if (status) @@ -3970,7 +4022,8 @@ srtp_unprotect_rtcp_mki(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len, unsigne /* if we're decrypting, exor keystream into the message */ if (enc_start) { - status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t *)enc_start, &enc_octet_len); + status = srtp_cipher_decrypt(session_keys->rtcp_cipher, (uint8_t *)enc_start, + &enc_octet_len); if (status) return srtp_err_status_cipher_fail; }