📄 srtp.c
字号:
} else { auth_start = NULL; auth_tag = NULL; } /* * if we expect message authentication, run the authentication * function and compare the result with the value of the auth_tag */ if (auth_start) { /* * if we're using a universal hash, then we need to compute the * keystream prefix for encrypting the universal hash output * * 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) { prefix_len = auth_get_prefix_length(stream->rtp_auth); status = cipher_output(stream->rtp_cipher, tmp_tag, prefix_len); debug_print(mod_srtp, "keystream prefix: %s", octet_string_hex_string(tmp_tag, prefix_len)); if (status) return err_status_cipher_fail; } /* initialize auth func context */ status = auth_start(stream->rtp_auth); if (status) return status; /* now compute auth function over packet */ status = auth_update(stream->rtp_auth, (uint8_t *)auth_start, *pkt_octet_len - tag_len); /* run auth func over ROC, then write tmp tag */ status = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, tmp_tag); debug_print(mod_srtp, "computed auth tag: %s", octet_string_hex_string(tmp_tag, tag_len)); debug_print(mod_srtp, "packet auth tag: %s", octet_string_hex_string(auth_tag, tag_len)); if (status) return err_status_auth_fail; if (octet_string_is_eq(tmp_tag, auth_tag, tag_len)) return err_status_auth_fail; } /* * update the key usage limit, and check it to make sure that we * didn't just hit either the soft limit or the hard limit, and call * the event handler if we hit either. */ switch(key_limit_update(stream->limit)) { case key_event_normal: break; case key_event_soft_limit: srtp_handle_event(ctx, stream, event_key_soft_limit); break; case key_event_hard_limit: srtp_handle_event(ctx, stream, event_key_hard_limit); return err_status_key_expired; default: break; } /* if we're encrypting, add keystream into ciphertext */ if (enc_start) { status = cipher_encrypt(stream->rtp_cipher, (uint8_t *)enc_start, &enc_octet_len); if (status) return err_status_cipher_fail; } /* * verify that stream is for received traffic - this check will * detect SSRC collisions, since a stream that appears in both * srtp_protect() and srtp_unprotect() will fail this test in one of * those functions. * * we do this check *after* the authentication check, so that the * latter check will catch any attempts to fool us into thinking * that we've got a collision */ if (stream->direction != dir_srtp_receiver) { if (stream->direction == dir_unknown) { stream->direction = dir_srtp_receiver; } else { srtp_handle_event(ctx, stream, event_ssrc_collision); } } /* * if the stream is a 'provisional' one, in which the template context * is used, then we need to allocate a new stream at this point, since * the authentication passed */ if (stream == ctx->stream_template) { srtp_stream_ctx_t *new_stream; /* * allocate and initialize a new stream * * note that we indicate failure if we can't allocate the new * stream, and some implementations will want to not return * failure here */ status = srtp_stream_clone(ctx->stream_template, hdr->ssrc, &new_stream); if (status) return status; /* add new stream to the head of the stream_list */ new_stream->next = ctx->stream_list; ctx->stream_list = new_stream; /* set stream (the pointer used in this function) */ stream = new_stream; } /* * the message authentication function passed, so add the packet * index into the replay database */ rdbx_add_index(&stream->rtp_rdbx, delta); /* decrease the packet length by the length of the auth tag */ *pkt_octet_len -= tag_len; return err_status_ok; }err_status_tsrtp_init() { err_status_t status; /* initialize crypto kernel */ status = crypto_kernel_init(); if (status) return status; /* load srtp debug module into the kernel */ status = crypto_kernel_load_debug_module(&mod_srtp); if (status) return status; return err_status_ok;}/* * The following code is under consideration for removal. See * SRTP_MAX_TRAILER_LEN */#if 0/* * srtp_get_trailer_length(&a) returns the number of octets that will * be added to an RTP packet by the SRTP processing. This value * is constant for a given srtp_stream_t (i.e. between initializations). */intsrtp_get_trailer_length(const srtp_stream_t s) { return auth_get_tag_length(s->rtp_auth);}#endif/* * srtp_get_stream(ssrc) returns a pointer to the stream corresponding * to ssrc, or NULL if no stream exists for that ssrc * * this is an internal function */srtp_stream_ctx_t *srtp_get_stream(srtp_t srtp, uint32_t ssrc) { srtp_stream_ctx_t *stream; /* walk down list until ssrc is found */ stream = srtp->stream_list; while (stream != NULL) { if (stream->ssrc == ssrc) return stream; stream = stream->next; } /* we haven't found our ssrc, so return a null */ return NULL;}err_status_tsrtp_dealloc(srtp_t session) { srtp_stream_ctx_t *stream; err_status_t status; /* * we take a conservative deallocation strategy - if we encounter an * error deallocating a stream, then we stop trying to deallocate * memory and just return an error */ /* walk list of streams, deallocating as we go */ stream = session->stream_list; while (stream != NULL) { srtp_stream_t next = stream->next; status = srtp_stream_dealloc(session, stream); if (status) return status; stream = next; } /* deallocate stream template, if there is one */ if (session->stream_template != NULL) { status = auth_dealloc(session->stream_template->rtcp_auth); if (status) return status; status = cipher_dealloc(session->stream_template->rtcp_cipher); if (status) return status; crypto_free(session->stream_template->limit); status = cipher_dealloc(session->stream_template->rtp_cipher); if (status) return status; status = auth_dealloc(session->stream_template->rtp_auth); if (status) return status; crypto_free(session->stream_template); } /* deallocate session context */ crypto_free(session); return err_status_ok;}err_status_tsrtp_add_stream(srtp_t session, const srtp_policy_t *policy) { err_status_t status; srtp_stream_t tmp; /* sanity check arguments */ if ((session == NULL) || (policy == NULL) || (policy->key == NULL)) return err_status_bad_param; /* allocate stream */ status = srtp_stream_alloc(&tmp, policy); if (status) { return status; } /* initialize stream */ status = srtp_stream_init(tmp, policy); if (status) { crypto_free(tmp); return status; } /* * set the head of the stream list or the template to point to the * stream that we've just alloced and init'ed, depending on whether * or not it has a wildcard SSRC value or not * * if the template stream has already been set, then the policy is * inconsistent, so we return a bad_param error code */ switch (policy->ssrc.type) { case (ssrc_any_outbound): if (session->stream_template) { return err_status_bad_param; } session->stream_template = tmp; session->stream_template->direction = dir_srtp_sender; break; case (ssrc_any_inbound): if (session->stream_template) { return err_status_bad_param; } session->stream_template = tmp; session->stream_template->direction = dir_srtp_receiver; break; case (ssrc_specific): tmp->next = session->stream_list; session->stream_list = tmp; break; case (ssrc_undefined): default: crypto_free(tmp); return err_status_bad_param; } return err_status_ok;}err_status_tsrtp_create(srtp_t *session, /* handle for session */ const srtp_policy_t *policy) { /* SRTP policy (list) */ err_status_t stat; srtp_ctx_t *ctx; /* sanity check arguments */ if (session == NULL) return err_status_bad_param; /* allocate srtp context and set ctx_ptr */ ctx = (srtp_ctx_t *) crypto_alloc(sizeof(srtp_ctx_t)); if (ctx == NULL) return err_status_alloc_fail; *session = ctx; /* * loop over elements in the policy list, allocating and * initializing a stream for each element */ ctx->stream_template = NULL; ctx->stream_list = NULL; while (policy != NULL) { stat = srtp_add_stream(ctx, policy); if (stat) { /* clean up everything */ srtp_dealloc(*session); return stat; } /* set policy to next item in list */ policy = policy->next; } return err_status_ok;}err_status_tsrtp_remove_stream(srtp_t session, uint32_t ssrc) { srtp_stream_ctx_t *stream, *last_stream; err_status_t status; /* sanity check arguments */ if (session == NULL) return err_status_bad_param; /* find stream in list; complain if not found */ last_stream = stream = session->stream_list; while ((stream != NULL) && (ssrc != stream->ssrc)) { last_stream = stream; stream = stream->next; } if (stream == NULL) return err_status_no_ctx; /* remove stream from the list */ last_stream->next = stream->next; /* deallocate the stream */ status = srtp_stream_dealloc(session, stream); if (status) return status; return err_status_ok;}/* * the default policy - provides a convenient way for callers to use * the default security policy * * this policy is that defined in the current SRTP internet draft. * *//* * NOTE: cipher_key_len is really key len (128 bits) plus salt len * (112 bits) *//* There are hard-coded 16's for base_key_len in the key generation code */voidcrypto_policy_set_rtp_default(crypto_policy_t *p) { p->cipher_type = AES_128_ICM; p->cipher_key_len = 30; /* default 128 bits per RFC 3711 */ p->auth_type = HMAC_SHA1; p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ p->sec_serv = sec_serv_conf_and_auth; }voidcrypto_policy_set_rtcp_default(crypto_policy_t *p) { p->cipher_type = AES_128_ICM; p->cipher_key_len = 30; /* default 128 bits per RFC 3711 */ p->auth_type = HMAC_SHA1; p->auth_key_len = 20; /* default 160 bits per RFC 3711 */ p->auth_tag_len = 10; /* default 80 bits per RFC 3711 */ p->sec_serv = sec_serv_conf_and_auth; }voidcrypto_policy_set_aes_cm_128_hmac_sha1_32(crypto_policy_t *p) { /* * corresponds to draft-ietf-mmusic-sdescriptions-12.txt * * note that this crypto policy is intended for SRTP, but not SRTCP */ p->cipher_type = AES_128_ICM; p->cipher_key_len = 30; /* 128 bit key, 112 bit salt */ p->auth_type = HMAC_SHA1; p->auth_key_len = 20; /* 160 bit key */ p->auth_tag_len = 4; /* 32 bit tag */ p->sec_serv = sec_serv_conf_and_auth; }voidcrypto_policy_set_aes_cm_128_null_auth(crypto_policy_t *p) { /* * corresponds to draft-ietf-mmusic-sdescriptions-12.txt * * note that this crypto policy is intended for SRTP, but not SRTCP */ p->cipher_type = AES_128_ICM; p->cipher_key_len = 30; /* 128 bit key, 112 bit salt */ p->auth_type = NULL_AUTH; p->auth_key_len = 0; p->auth_tag_len = 0; p->sec_serv = sec_serv_conf; }voidcrypto_policy_set_null_cipher_hmac_sha1_80(crypto_policy_t *p) { /* * corresponds to draft-ietf-mmusic-sdescriptions-12.txt */ p->cipher_type = NULL_CIPHER; p->cipher_key_len = 0; p->auth_type = HMAC_SHA1; p->auth_key_len = 20; p->auth_tag_len = 10; p->sec_serv = sec_serv_auth; }/* * secure rtcp functions */err_status_t srtp_protect_rtcp(srtp_t ctx, void *rtcp_hdr, int *pkt_octet_len) { 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 */ uint32_t *trailer; /* pointer to start of trailer */ unsigned enc_octet_len = 0;/* number of octets in encrypted portion */ uint8_t *auth_tag = NULL; /* location of auth_tag within packet */ err_status_t status; int tag_len; srtp_stream_ctx_t *stream; int prefix_len; uint32_t seq_num;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -