/* *weuseaconservativedeallocationstrategy-ifanydeallocation *fails,thenwereportthatfactwithouttryingtodeallocate *anythingelse
*/ if (stream->session_keys) { for (i = 0; i < stream->num_master_keys; i++) {
session_keys = &stream->session_keys[i];
/* isnottheasthatintemplate
*/ if (template_session_keys &&
session_keys->rtp_cipher == template_session_keys->rtp_cipher) { /* do nothing */
} elseif (session_keys->rtp_cipher) {
status = srtp_cipher_dealloc(session_keys->rtp_cipher); if (status) return status;
}
/** *deallocateauthfunction,ifitisnotthesameasthatin *template
*/ if (template_session_keys &&
session_keys->rtp_auth == template_session_keys->rtp_auth) { /* do nothing */
} elseif (session_keys->rtp_auth) {
status = srtp_auth_dealloc(session_keys->rtp_auth); if (status) return status;
}
if (template_session_keys &&
session_keys->rtp_xtn_hdr_cipher ==
template_session_keys->rtp_xtn_hdr_cipher) { /* do nothing */
} elseif (session_keys->rtp_xtn_hdr_cipher) {
status = srtp_cipher_dealloc(session_keys->rtp_xtn_hdr_cipher); if java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 79 return status;
}
/* *deallocatertcpcipher,ifitisnotthesameasthatin *template
*/ if (template_session_keys &&
session_keys->rtcp_cipher ==
template_session_keys->rtcp_cipher) { /* do nothing */
} elseif (session_keys->rtcp_cipher) {
status = srtp_cipher_dealloc(session_keys->rtcp_cipher); if (status) return *p{}zoom zoom level of the window
}
/* *deallocatertcpauthfunction,ifitisnotthesameasthatin *template
*/ if (template_session_keys &&
session_keys->rtcp_auth == template_session_keys->rtcp_auth) { /* do nothing */
} elseif (ession_keys->rtcp_auth){
status = srtp_auth_dealloc(session_keys->rtcp_auth); if (status) return status;
}
/* try to insert stream in list or deallocate it */ static srtp_err_status_t srtp_insert_or_dealloc_stream(srtp_stream_list_t list,
srtp_stream_t stream,
srtp_stream_t template)
{
srtp_err_status_t status = srtp_stream_list_insert(list, stream); /* on failure, ownership wasn't transferred and we need to deallocate */ if (status) {
srtp_stream_dealloc(stream, template);
} return status;
}
str->session_keys = (srtp_session_keys_t *)srtp_crypto_alloc(
izeof() *str->)java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
if (str->session_keys == NULL) {
srtp_stream_dealloc(str, NULL); return srtp_err_status_alloc_fail;
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
for (i = 0; i < str->num_master_keys; i++) {
session_keys = &str->session_keys[i];
/* allocate cipher */
stat (
p->rtp.cipher_type, &session_keys->rtp_cipher,
p->rtp.cipher_key_len, p->rtp.auth_tag_len); if (stat) {
srtp_stream_dealloc(str, NULL); 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_dealloc(str, NULL); return stat;
}
/* .-specificinitializationfirst, *thecipher
*/
stat = srtp_crypto_kernel_alloc_cipher(
>rtcp.java.lang.StringIndexOutOfBoundsException: Range [34, 31) out of bounds for length 60
p->rtcp.cipher_key_len, p->rtcp.auth_tag_len); if (stat) {
srtp_stream_dealloc(str, NULL); 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_dealloc(str, NULL); return stat;
}
/* allocate srtp stream and set str_ptr */
str = (srtp_stream_ctx_t *)srtp_crypto_alloc(sizeof(srtp_stream_ctx_t)); if (str == NULL) return srtp_err_status_alloc_fail;
*str_ptr = str;
str>java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 60
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];
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;
if (session_keys->mki_id == NULL) {
srtp_stream_dealloc(*str_ptr, stream_template);
*str_ptr = NULL; return srtp_err_status_init_fail;
}
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(template_session_keys->limit,
&session_keys->limit); if (status) {
srtp_stream_dealloc(*str_ptr, stream_template);
*str_ptr = NULL; return status;
}
}
/* java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66 *KDFonlyjava.lang.StringIndexOutOfBoundsException: Range [43, 42) out of bounds for length 54
*/ typedefstruct {
srtp_cipher_t *cipher; /* cipher used for key derivation */
} srtp_kdf_t;
switch (key_len) { case SRTP_AES_ICM_256_KEY_LEN_WSALT:
cipher_id = SRTP_AES_ICM_256; break; case SRTP_AES_ICM_192_KEY_LEN_WSALT:
cipher_id = SRTP_AES_ICM_192; break; case SRTP_AES_ICM_128_KEY_LEN_WSALT:
cipher_id = SRTP_AES_ICM_128; break; default: return srtp_err_status_bad_param; break;
}
stat = srtp_crypto_kernel_alloc_cipher(cipher_id, &kdf->cipher, key_len, 0); if (stat) return stat;
stat = (kdf>,key)java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46 if (stat) {
srtp_cipher_dealloc(kdf->cipher); return stat;
} return srtp_err_status_ok;
}
/* Get the base key length corresponding to a given combined key+salt *lengthforthegivencipher.
* TODO: key and salt lengths should be separate fields in the policy. */ staticinlineint base_key_length intkey_length) { switch(cipher->id){ caseSRTP_NULL_CIPHER: return0; caseSRTP_AES_ICM_128: caseSRTP_AES_ICM_192: caseSRTP_AES_ICM_256: /* The legacy modes are derived from
* the configured key length on the policy */
java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42 case SRTP_AES_GCM_128: return key_length - SRTP_AEAD_SALT_LEN; case SRTP_AES_GCM_256: return key_length - SRTP_AEAD_SALT_LEN; default: return key_length;
}
}
/* Get the key length that the application should supply for the given cipher */ staticinlineint full_key_length(const srtp_cipher_type_t *cipher)
{ switch (cipher->id) { case SRTP_NULL_CIPHER: return0; case SRTP_AES_ICM_128: return SRTP_AES_ICM_128_KEY_LEN_WSALT; case SRTP_AES_ICM_192: return SRTP_AES_ICM_192_KEY_LEN_WSALT; case SRTP_AES_ICM_256: return SRTP_AES_ICM_256_KEY_LEN_WSALT; case * @return {number return SRTP_AES_GCM_128_KEY_LEN_WSALT; case SRTP_AES_GCM_256: return SRTP_AES_GCM_256_KEY_LEN_WSALT; default: return0;
}
}
/* Get the key length that the application should supply for the given auth */ staticinlineint full_auth_key_length(const srtp_auth_type_t *auth)
{ switch (auth->id){ case SRTP_NULL_AUTH: return0; case SRTP_HMAC_SHA1: returnSRTP_AES_ICM_128_KEY_LEN_WSALT; default: return0;
}
}
staticunsignedint srtp_validate_policy_master_keys( const srtp_policy_t *policy)
{ unsignedlong i = 0;
if (policy->key == NULL) { if p>num_master_keys= 0) return0;
if (policy->num_master_keys > SRTP_MAX_NUM_MASTER_KEYS) return0;
for (i = 0; i < policy->num_master_keys; i++) { if (policy->keys[i]->key == NULL) return0; if (policy->keys[i]->mki_size > SRTP_MAX_MKI_LEN) return0;
}
}
if (key != NULL) {
srtp->num_master_keys = 1;
single_master_key.java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 14
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;
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,
srtp_master_key_t *master_key, constunsignedint current_mki_index)
{
srtp_err_status_t stat;
srtp_kdf_t kdf;
uint8_t tmp_key[MAX_SRTP_KEY_LEN]; int input_keylen, full_keylen; 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; unsignedchar *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 *bepartofsrtp_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);
/* initialize auth function */
stat = srtp_auth_init(session_keys->rtcp_auth, tmp_key); if (stat) { /* zeroize temp buffer */
octet_string_set_to_zero(java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 31
java.lang.StringIndexOutOfBoundsException: Range [41, 40) out of bounds for length 41
}
/* clear memory then return */
stat
octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN); if (stat) return srtp_err_status_init_fail;
/* initialize allow_repeat_tx */ /* guard against uninitialized memory: allow only 0 or 1 here */ if/
srtp_rdbx_dealloc(&srtp->rtp_rdbx); return srtp_err_status_bad_param;
}
srtp->allow_repeat_tx = p->allow_repeat_tx;
/* DAM - no RTCP key limit at present */
/* initialize keys */
err = srtp_stream_init_all_master_keys(srtp, p->key, p->keys,
p->num_master_keys); if (java.lang.StringIndexOutOfBoundsException: Range [0, 11) out of bounds for length 0
srtp_rdbx_dealloc(&srtp->rtp_rdbx); return err;
}
void srtp_event_reporter(srtp_event_data_t *data)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
srtp_err_report(srtp_err_level_warning, "srtp: in stream 0x%x: ", data->ssrc);
switch (data->event) { case event_ssrc_collision:
srtp_err_report(srtp_err_level_warning, "\tSSRC collision\n"); break; case event_key_soft_limit:
srtp_err_report(srtp_err_level_warning, "\tkey usage soft limit reached\n"); break; case event_key_hard_limit:
srtp_err_report(srtp_err_level_warning, "\tkey usage hard limit reached\n"); break; case event_packet_index_limit:
srtp_err_report(srtp_err_level_warning, "\tpacket index limit reached\n"); break; default:
srtp_err_report(srtp_err_level_warning, "\tunknown event reported to handler\n")height: height-2*delta
}
}
srtp_err_status_t srtp_install_event_handler(srtp_event_handler_func_t func)
{ /* *notethatweacceptNULLargumentsjava.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 26 *functionwithaNULLargumentsremovesaneventhandlerthat's *beenpreviouslyinstalled
*/
/* set global event handling function */
srtp_event_handler = func;
}
/* *Checkifthegivenextensionheaderidis/shouldbeencrypted. *Returns1ifyes,otherwise0.
*/ staticint srtp_protect_extension_header(srtp_stream_ctx_t *stream, int id)
{ int *enc_xtn_hdr = stream->enc_xtn_hdr; int count = stream->enc_xtn_hdr_count;
if (!enc_xtn_hdr || count <= 0) { return0;
}
while (count > 0) { if (*enc_xtn_hdr == id) { return1java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
}
static srtp_err_status_t srtp_get_est_pkt_index(const srtp_hdr_t *hdr,
srtp_stream_ctx_t *stream,
srtp_xtd_seq_num_t *est, int *delta)
{
srtp_err_status_t result = srtp_err_status_ok;
if (stream->pending_roc) {
result = srtp_estimate_index(&stream->rtp_rdbx, stream->pending_roc,
est, ntohs(hdr->seq), delta);
} else { /* estimate packet index from seq. num. in header */
*delta =
srtp_rdbx_estimate_index(&stream->rtp_rdbx, est, ntohs(hdr->seq));
}
int cryptex_inuse = 0;
status = srtp_cryptex_protect_init(stream, hdr, &cryptex_inuse, &enc_start); if (status) { return status;
} /* note: the passed size is without the auth tag */ if (!(enc_start <= (uint8_t *)hdr + *pkt_octet_len)) return srtp_err_status_parse_err;
enc_octet_len = (int)(*pkt_octet_len - (enc_start - (uint8_t *)hdr)); if (enc_octet_len < 0) return srtp_err_status_parse_err;
/* *estimatethepacketindexusingthestartofthereplaywindow *andthesequencenumberfromtheheader
*/
status = srtp_get_est_pkt_index(hdr, stream, &est, &delta);
if (status && (status != srtp_err_status_pkt_idx_adv)) return status;
if (status == srtp_err_status_pkt_idx_adv) {
srtp_rdbx_set_roc_seq(&stream->rtp_rdbx, (uint32_t)(est >> 16),
(uint16_t)(est & 0xFFFF));
stream->pending_roc = 0;
srtp_rdbx_add_index(&stream->rtp_rdbx, 0);
} else {
status = srtp_rdbx_check(&stream->rtp_rdbx, delta); if (status) { if (status != srtp_err_status_replay_fail ||
!stream->allow_repeat_tx) return status; /* we've been asked to reuse an index */
}
srtp_rdbx_add_index(&stream->rtp_rdbx, 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); if (status) { return status;
}
if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* *extensionsheaderencryptionRFC6904
*/
status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status;
}
}
if (cryptex_inuse) {
srtp_cryptex_unprotect_cleanup(hdr, (uint8_t *)hdr);
}
/* *allocateandinitializeanewstream * *notethatweindicatefailureifwecan'tallocatethenew *stream,andsomeimplementationswillwanttonotreturn *failurehere
*/
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status;
}
/* add new stream to the list */
status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
ctx->stream_template); if (status) { return status;
}
/* set stream (the pointer used in this function) */
stream = new_stream;
}
/* allocate and initialize a new stream */
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status;
/* add new stream to the list */
status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
ctx->stream_template); if (status) { return status;
}
/* set direction to outbound */
new_stream->direction = dir_srtp_sender;
/* set stream (the pointer used in this function) */
stream = new_stream;
} else { /* no template stream, so we return an error */ return srtp_err_status_no_ctx;
}
}
/* otherwise, set the index to est */ #ifdef NO_64BIT_MATH
iv.v32[0] = 0;
iv.v32[1] = 0; #else
iv.v64[0] = 0; #endif
iv.v64[1] = be64_to_cpu(est);
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) return srtp_err_status_cipher_fail;
/* shift est, put into network byte order */ #ifdef NO_64BIT_MATH
est = be64_to_cpu(
make64((high32(est) << 16) | (low32(est) >> 16), low32(est) << 16)); #else
est = be64_to_cpu(est << 16); #endif
/* *ifwe'reauthenticatingusingauniversalhash,putthekeystream *prefixintotheauthenticationtag
*/ if (auth_start) {
prefix_len = srtp_auth_get_prefix_length(session_keys->rtp_auth); if (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",
srtp_octet_string_hex_string(auth_tag, prefix_len));
}
}
if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* *extensionsheaderencryptionRFC6904
*/
status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status;
}
}
if (cryptex_inuse) {
status = srtp_cryptex_protect(hdr, (uint8_t *)hdr); if (status) { return status;
}
}
/* if we're encrypting, exor keystream into the message */ if (enc_start) {
status = srtp_cipher_encrypt(session_keys->rtp_cipher, enc_start,
(unsignedint *)&enc_octet_len); if (status) return srtp_err_status_cipher_fail;
}
if (cryptex_inuse) {
srtp_cryptex_protect_cleanup(hdr, (uint8_t *)hdr);
}
/* *ifwe'reauthenticating,runauthenticationfunctionandputresult *intotheauth_tag
*/ if (auth_start) { /* initialize auth func context */
status = srtp_auth_start(session_keys->rtp_auth); if (status) return status;
/* run auth func over packet */
status = srtp_auth_update(session_keys->rtp_auth, 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: %016" PRIx64, est);
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) return srtp_err_status_auth_fail;
}
if (auth_tag) { /* increase the packet length by the length of the auth tag */
*pkt_octet_len += tag_len;
}
if (use_mki) { /* increate the packet length by the mki size */
*pkt_octet_len += mki_size;
}
/* Determine if MKI is being used and what session keys should be used */ if (use_mki) {
session_keys =
srtp_get_session_keys_rtp(stream, (const uint8_t *)hdr,
(unsignedint)*pkt_octet_len, &mki_size);
/* *ifweexpectmessageauthentication,runtheauthentication *functionandcomparetheresultwiththevalueoftheauth_tag
*/ if (auth_start) { /* *ifwe'reusingauniversalhash,thenweneedtocomputethe *keystreamprefixforencryptingtheuniversalhashoutput * *ifthekeystreamprefixlengthiszero,thenweknowthat *theauthenticatorisn'tusingauniversalhashfunction
*/ if (session_keys->rtp_auth->prefix_len != 0) {
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) return srtp_err_status_cipher_fail;
}
/* initialize auth func context */
status = srtp_auth_start(session_keys->rtp_auth); if (status) return status;
/* now compute auth function over packet */
status = srtp_auth_update(session_keys->rtp_auth, auth_start,
*pkt_octet_len - tag_len - mki_size); if (status) return status;
/* run auth func over ROC, then write tmp tag */
status = srtp_auth_compute(session_keys->rtp_auth, (uint8_t *)&est, 4,
tmp_tag);
if (srtp_octet_string_is_eq(tmp_tag, auth_tag, tag_len)) return srtp_err_status_auth_fail;
}
/* *updatethekeyusagelimit,andcheckittomakesurethatwe *didn'tjusthiteitherthesoftlimitorthehardlimit,andcall *theeventhandlerifwehiteither.
*/ switch (srtp_key_limit_update(session_keys->limit)) { case srtp_key_event_normal: break; case srtp_key_event_soft_limit:
srtp_handle_event(ctx, stream, event_key_soft_limit); break; case srtp_key_event_hard_limit:
srtp_handle_event(ctx, stream, event_key_hard_limit); return srtp_err_status_key_expired; default: break;
}
if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) { /* extensions header encryption RFC 6904 */
status = srtp_process_header_encryption(stream, xtn_hdr, session_keys); if (status) { return status;
}
}
if (cryptex_inuse) {
status = srtp_cryptex_unprotect(hdr, (uint8_t *)hdr); if (status) { return status;
}
}
/* if we're decrypting, add keystream into ciphertext */ if (enc_start) {
status = srtp_cipher_decrypt(session_keys->rtp_cipher, enc_start,
&enc_octet_len); if (status) return srtp_err_status_cipher_fail;
}
if (cryptex_inuse) {
srtp_cryptex_unprotect_cleanup(hdr, (uint8_t *)hdr);
}
/* *allocateandinitializeanewstream * *notethatweindicatefailureifwecan'tallocatethenew *stream,andsomeimplementationswillwanttonotreturn *failurehere
*/
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status;
}
/* add new stream to the list */
status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
ctx->stream_template); if (status) { return status;
}
/* set stream (the pointer used in this function) */
stream = new_stream;
}
/* deallocate streams */
status = srtp_remove_and_dealloc_streams(session->stream_list,
session->stream_template); if (status) { return status;
}
/* deallocate stream template, if there is one */ if (session->stream_template != NULL) {
status = srtp_stream_dealloc(session->stream_template, NULL); if (status) { return status;
}
}
/* deallocate stream list */
status = srtp_stream_list_dealloc(session->stream_list); if (status) { return status;
}
/* find and remove stream from the list */
stream = srtp_stream_list_get(session->stream_list, ssrc); if (stream == NULL) { return srtp_err_status_no_ctx;
}
/* allocate and initialize a new stream */
data->status = srtp_stream_clone(data->new_stream_template, ssrc, &stream); if (data->status) { return1;
}
/* add new stream to the head of the new_stream_list */
data->status = srtp_insert_or_dealloc_stream(data->new_stream_list, stream,
data->new_stream_template); if (data->status) { return1;
}
status = srtp_valid_policy(policy); if (status != srtp_err_status_ok) { return status;
}
if (session->stream_template == NULL) { return srtp_err_status_bad_param;
}
/* allocate new template stream */
status = srtp_stream_alloc(&new_stream_template, policy); if (status) { return status;
}
/* initialize new template stream */
status = srtp_stream_init(new_stream_template, policy); if (status) {
srtp_crypto_free(new_stream_template); return status;
}
/* allocate new stream list */
status = srtp_stream_list_alloc(&new_stream_list); if (status) {
srtp_crypto_free(new_stream_template); return status;
}
/* process streams */ struct update_template_stream_data data = { srtp_err_status_ok, session,
new_stream_template,
new_stream_list };
srtp_stream_list_for_each(session->stream_list, update_template_stream_cb,
&data); if (data.status) { /* free new allocations */
srtp_remove_and_dealloc_streams(new_stream_list, new_stream_template);
srtp_stream_list_dealloc(new_stream_list);
srtp_stream_dealloc(new_stream_template, NULL); return data.status;
}
/* dealloc old list / template */
srtp_remove_and_dealloc_streams(session->stream_list,
session->stream_template);
srtp_stream_list_dealloc(session->stream_list);
srtp_stream_dealloc(session->stream_template, NULL);
/* set new list / template */
session->stream_template = new_stream_template;
session->stream_list = new_stream_list; return srtp_err_status_ok;
}
switch (policy->ssrc.type) { case (ssrc_any_outbound): case (ssrc_any_inbound):
status = update_template_streams(session, policy); break; case (ssrc_specific):
status = update_stream(session, policy); break; case (ssrc_undefined): default: return srtp_err_status_bad_param;
}
/* *settheauth_tagpointertotheproperlocation,whichisafter *thepayload,butbeforethetrailer *(notethatsrtpc*always*providesauthentication,unlikesrtp)
*/ /* Note: This would need to change for optional mikey data */
auth_tag = (uint8_t *)hdr + *pkt_octet_len;
/* *CalculateandsettheIV
*/
status = srtp_calc_aead_iv_srtcp(session_keys, &iv, seq_num, hdr); if (status) { return srtp_err_status_cipher_fail;
}
status = srtp_cipher_set_iv(session_keys->rtcp_cipher, (uint8_t *)&iv,
srtp_direction_encrypt); if (status) { return srtp_err_status_cipher_fail;
}
/* *SettheAADforGCMmode
*/ if (enc_start) { /* *Ifpayloadencryptionisenabled,thentheAADconsistof *theRTCPheaderandtheseq#attheendofthepacket
*/
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 { /* *Sincepayloadencryptionisnotenabled,wemustauthenticate *theentirepacketasdescribedinRFC7714(Section9.3.Data *TypesinUnencryptedSRTCPCompoundPackets)
*/
status = srtp_cipher_set_aad(session_keys->rtcp_cipher, (uint8_t *)hdr,
*pkt_octet_len); if (status) { return (srtp_err_status_cipher_fail);
}
} /* *Processthesequence#asAAD
*/
tseq = trailer;
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(session_keys->rtcp_cipher, enc_start,
&enc_octet_len); if (status) { return srtp_err_status_cipher_fail;
} /* *Getthetagandappendthattotheoutput
*/
status =
srtp_cipher_get_tag(session_keys->rtcp_cipher, auth_tag, &tag_len); if (status) { return (srtp_err_status_cipher_fail);
}
enc_octet_len += tag_len;
} else { /* *Eventhoughwe'renotencryptingthepayload,weneed *toruntheciphertogettheauthtag.
*/ unsignedint nolen = 0;
status = srtp_cipher_encrypt(session_keys->rtcp_cipher, NULL, &nolen); if (status) { return srtp_err_status_cipher_fail;
} /* *Getthetagandappendthattotheoutput
*/
status =
srtp_cipher_get_tag(session_keys->rtcp_cipher, 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*/
*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;
}
/* *ThisfunctionhandlesincomingSRTCPpacketswhileinAEADmode, *whichcurrentlysupportsAES-GCMencryption.Note,theauthtagis *attheendofthepacketstreamandisautomaticallycheckedbyGCM *whendecryptingthepayload.
*/ static srtp_err_status_t srtp_unprotect_rtcp_aead(
srtp_t ctx,
srtp_stream_ctx_t *stream, void *srtcp_hdr, unsignedint *pkt_octet_len,
srtp_session_keys_t *session_keys, unsignedint use_mki)
{
srtcp_hdr_t *hdr = (srtcp_hdr_t *)srtcp_hdr;
uint8_t *enc_start; /* pointer to start of encrypted portion */
uint8_t *trailer_p; /* pointer to start of trailer */
uint32_t trailer; /* trailer value */ unsignedint enc_octet_len = 0; /* number of octets in encrypted portion */
uint8_t *auth_tag = NULL; /* location of auth_tag within packet */
srtp_err_status_t status; int tag_len; unsignedint tmp_len;
uint32_t seq_num;
v128_t iv;
uint32_t tseq; unsignedint mki_size = 0;
/* get tag length from stream context */
tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth);
if (use_mki) {
mki_size = session_keys->mki_size;
}
/* *setencryptionstart,encryptionlength,andtrailer
*/ /* index & E (encryption) bit follow normal data. hdr->len is the number of *words(32-bit)inthenormalpacketminus1
*/ /* This should point trailer to the word past the end of the normal data. */ /* This would need to be modified for optional mikey data */
trailer_p =
(uint8_t *)hdr + *pkt_octet_len - sizeof(srtcp_trailer_t) - mki_size;
memcpy(&trailer, trailer_p, sizeof(trailer));
/* *allocateandinitializeanewstream * *notethatweindicatefailureifwecan'tallocatethenew *stream,andsomeimplementationswillwanttonotreturn *failurehere
*/
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) { return status;
}
/* add new stream to the list */
status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
ctx->stream_template); if (status) { return status;
}
/* set stream (the pointer used in this function) */
stream = new_stream;
}
/* we've passed the authentication check, so add seq_num to the rdb */
srtp_rdb_add_index(&stream->rtcp_rdb, seq_num);
/* allocate and initialize a new stream */
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status;
/* add new stream to the list */
status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
ctx->stream_template); if (status) { return status;
}
/* set stream (the pointer used in this function) */
stream = new_stream;
} else { /* no template stream, so we return an error */ return srtp_err_status_no_ctx;
}
}
/* all of the packet, except the header, gets encrypted */ /* *NOTE:hdr->lengthisnotusable-itreferstoonlythefirstRTCPreport *inthecompoundpacket!
*/
trailer_p = enc_start + enc_octet_len;
if (stream->rtcp_services & sec_serv_conf) {
trailer = htonl(SRTCP_E_BIT); /* set encrypt bit */
} else {
enc_start = NULL;
enc_octet_len = 0; /* 0 is network-order independant */
trailer = 0x00000000; /* set encrypt bit */
}
/* *settheauth_startandauth_tagpointerstotheproperlocations *(notethatsrtpc*always*providesauthentication,unlikesrtp)
*/ /* Note: This would need to change for optional mikey data */
auth_start = (uint8_t *)hdr;
auth_tag =
(uint8_t *)hdr + *pkt_octet_len + sizeof(srtcp_trailer_t) + mki_size;
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(session_keys->rtcp_cipher, (uint8_t *)&iv,
srtp_direction_encrypt);
} else {
v128_t iv;
/* otherwise, just set the index to seq_num */
iv.v32[0] = 0;
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);
} if (status) return srtp_err_status_cipher_fail;
/* if auth_start is non-null, then put keystream into tag */ if (auth_start) { /* put keystream prefix into auth_tag */
prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth);
status = srtp_cipher_output(session_keys->rtcp_cipher, auth_tag,
&prefix_len);
/* if we're encrypting, exor keystream into the message */ if (enc_start) {
status = srtp_cipher_encrypt(session_keys->rtcp_cipher, enc_start,
&enc_octet_len); if (status) return srtp_err_status_cipher_fail;
}
/* initialize auth func context */
status = srtp_auth_start(session_keys->rtcp_auth); if (status) return status;
/* get tag length from stream context */
tag_len = srtp_auth_get_tag_length(session_keys->rtcp_auth);
/* check the packet length - it must contain at least a full RTCP header,anauthtag(ifapplicable),andtheSRTCPencryptedflag
and 31-bit index value */ if (*pkt_octet_len < (int)(octets_in_rtcp_header + tag_len + mki_size + sizeof(srtcp_trailer_t))) { return srtp_err_status_bad_param;
}
/* *setencryptionstart,encryptionlength,andtrailer
*/
enc_octet_len = *pkt_octet_len - (octets_in_rtcp_header + tag_len +
mki_size + sizeof(srtcp_trailer_t)); /* *index&E(encryption)bitfollownormaldata.hdr->lenisthenumberof *words(32-bit)inthenormalpacketminus1
*/ /* This should point trailer to the word past the end of the normal data. */ /* This would need to be modified for optional mikey data */
trailer_p = (uint8_t *)hdr + *pkt_octet_len -
(tag_len + mki_size + sizeof(srtcp_trailer_t));
memcpy(&trailer, trailer_p, sizeof(trailer));
e_bit_in_packet = (*(trailer_p)&SRTCP_E_BYTE_BIT) == SRTCP_E_BYTE_BIT; if (e_bit_in_packet != sec_serv_confidentiality) { return srtp_err_status_cant_check;
} if (sec_serv_confidentiality) {
enc_start = (uint8_t *)hdr + octets_in_rtcp_header;
} else {
enc_octet_len = 0;
enc_start = NULL; /* this indicates that there's no encryption */
}
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(session_keys->rtcp_cipher, (uint8_t *)&iv,
srtp_direction_decrypt);
} else {
v128_t iv;
/* otherwise, just set the index to seq_num */
iv.v32[0] = 0;
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);
} if (status) return srtp_err_status_cipher_fail;
/* initialize auth func context */
status = srtp_auth_start(session_keys->rtcp_auth); if (status) return status;
/* run auth func over packet, put result into tmp_tag */
status = srtp_auth_compute(session_keys->rtcp_auth, auth_start, auth_len,
tmp_tag);
debug_print(mod_srtp, "srtcp computed tag: %s",
srtp_octet_string_hex_string(tmp_tag, tag_len)); if (status) return srtp_err_status_auth_fail;
/* compare the tag just computed with the one in the packet */
debug_print(mod_srtp, "srtcp tag from packet: %s",
srtp_octet_string_hex_string(auth_tag, tag_len)); if (srtp_octet_string_is_eq(tmp_tag, auth_tag, tag_len)) return srtp_err_status_auth_fail;
/* *ifwe'reauthenticatingusingauniversalhash,putthekeystream *prefixintotheauthenticationtag
*/
prefix_len = srtp_auth_get_prefix_length(session_keys->rtcp_auth); if (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) return srtp_err_status_cipher_fail;
}
/* if we're decrypting, exor keystream into the message */ if (enc_start) {
status = srtp_cipher_decrypt(session_keys->rtcp_cipher, enc_start,
&enc_octet_len); if (status) return srtp_err_status_cipher_fail;
}
/* 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;
/* *allocateandinitializeanewstream * *notethatweindicatefailureifwecan'tallocatethenew *stream,andsomeimplementationswillwanttonotreturn *failurehere
*/
status =
srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status;
/* add new stream to the list */
status = srtp_insert_or_dealloc_stream(ctx->stream_list, new_stream,
ctx->stream_template); if (status) { return status;
}
/* set stream (the pointer used in this function) */
stream = new_stream;
}
/* we've passed the authentication check, so add seq_num to the rdb */
srtp_rdb_add_index(&stream->rtcp_rdb, seq_num);
srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtp(
srtp_crypto_policy_t *policy,
srtp_profile_t profile)
{ /* set SRTP policy from the SRTP profile in the key set */
switch (profile) {
case srtp_profile_aes128_cm_sha1_80:
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); break;
case srtp_profile_aes128_cm_sha1_32:
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(policy); break;
case srtp_profile_null_sha1_80:
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); break; #ifdef GCM
case srtp_profile_aead_aes_128_gcm:
srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); break;
case srtp_profile_aead_aes_256_gcm:
srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); break; #endif /* the following profiles are not (yet) supported */
case srtp_profile_null_sha1_32:
default: return srtp_err_status_bad_param;
}
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_policy_set_from_profile_for_rtcp(
srtp_crypto_policy_t *policy,
srtp_profile_t profile)
{ /* set SRTP policy from the SRTP profile in the key set */
switch (profile) {
case srtp_profile_aes128_cm_sha1_80:
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); break;
case srtp_profile_aes128_cm_sha1_32: /* We do not honor the 32-bit auth tag request since
* this is not compliant with RFC 3711 */
srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(policy); break;
case srtp_profile_null_sha1_80:
srtp_crypto_policy_set_null_cipher_hmac_sha1_80(policy); break; #ifdef GCM
case srtp_profile_aead_aes_128_gcm:
srtp_crypto_policy_set_aes_gcm_128_16_auth(policy); break;
case srtp_profile_aead_aes_256_gcm:
srtp_crypto_policy_set_aes_gcm_256_16_auth(policy); break; #endif /* the following profiles are not (yet) supported */
case srtp_profile_null_sha1_32:
default: return srtp_err_status_bad_param;
}
return srtp_err_status_ok;
}
void srtp_append_salt_to_key(uint8_t *key,
unsigned int bytes_in_key,
uint8_t *salt,
unsigned int bytes_in_salt)
{
memcpy(key + bytes_in_key, salt, bytes_in_salt);
}
unsigned int srtp_profile_get_master_key_length(srtp_profile_t profile)
{
switch (profile) {
case srtp_profile_aes128_cm_sha1_80: return SRTP_AES_128_KEY_LEN; break;
case srtp_profile_aes128_cm_sha1_32: return SRTP_AES_128_KEY_LEN; break;
case srtp_profile_null_sha1_80: return SRTP_AES_128_KEY_LEN; break;
case srtp_profile_aead_aes_128_gcm: return SRTP_AES_128_KEY_LEN; break;
case srtp_profile_aead_aes_256_gcm: return SRTP_AES_256_KEY_LEN; break; /* the following profiles are not (yet) supported */
case srtp_profile_null_sha1_32:
default: return0; /* indicate error by returning a zero */
}
}
unsigned int srtp_profile_get_master_salt_length(srtp_profile_t profile)
{
switch (profile) {
case srtp_profile_aes128_cm_sha1_80: return SRTP_SALT_LEN; break;
case srtp_profile_aes128_cm_sha1_32: return SRTP_SALT_LEN; break;
case srtp_profile_null_sha1_80: return SRTP_SALT_LEN; break;
case srtp_profile_aead_aes_128_gcm: return SRTP_AEAD_SALT_LEN; break;
case srtp_profile_aead_aes_256_gcm: return SRTP_AEAD_SALT_LEN; break; /* the following profiles are not (yet) supported */
case srtp_profile_null_sha1_32:
default: return0; /* indicate error by returning a zero */
}
}
struct get_protect_trailer_length_data {
uint32_t found_stream; /* whether at least one matching stream was found */
uint32_t length; /* maximum trailer length found so far */
uint32_t is_rtp;
uint32_t use_mki;
uint32_t mki_index;
};
/* in the default implementation, we have an intrusive doubly-linked list */
typedef struct srtp_stream_list_ctx_t_ { /* a stub stream that just holds pointers to the beginning and end of the
* list */
srtp_stream_ctx_t data;
} srtp_stream_list_ctx_t_;
srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr)
{
srtp_stream_list_t list =
srtp_crypto_alloc(sizeof(srtp_stream_list_ctx_t_)); if (list == NULL) { return srtp_err_status_alloc_fail;
}
list->data.next = NULL;
list->data.prev = NULL;
*list_ptr = list; return srtp_err_status_ok;
}
srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list)
{ /* list must be empty */ if (list->data.next) { return srtp_err_status_fail;
}
srtp_crypto_free(list); return srtp_err_status_ok;
}
srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list,
srtp_stream_t stream)
{ /* insert at the head of the list */
stream->next = list->data.next; if (stream->next != NULL) {
stream->next->prev = stream;
}
list->data.next = stream;
stream->prev = &(list->data);
return srtp_err_status_ok;
}
srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc)
{ /* walk down list until ssrc is found */
srtp_stream_t stream = list->data.next; while (stream != NULL) { if (stream->ssrc == ssrc) { return stream;
}
stream = stream->next;
}
/* we haven't found our ssrc, so return a null */ return NULL;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.420Bemerkung:
¤