Logo Search packages:      
Sourcecode: srtp version File versions  Download package

err_status_t srtp_protect_rtcp ( srtp_t  ctx,
void *  rtcp_hdr,
int *  pkt_octet_len 

srtp_protect_rtcp() is the Secure RTCP sender-side packet processing function.

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 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.

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.
ctxis the SRTP context to use in processing the packet.
rtcp_hdris a pointer to the RTCP packet (before the call); after the function returns, it points to the srtp packet.
pkt_octet_lenis 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 err_status_ok was returned. Otherwise, the value of the data to which it points is undefined.
  • err_status_ok if there were no problems.
  • [other] if there was a failure in the cryptographic mechanisms.

Definition at line 1420 of file srtp.c.

References err_status_auth_fail, err_status_cipher_fail, err_status_no_ctx, err_status_ok, event_ssrc_collision, and sec_serv_conf.

  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;

  /* we assume the hdr is 32-bit aligned to start */
   * look up ssrc in srtp_stream list, and process the packet with 
   * the appropriate stream.  if we haven't seen this stream before,
   * there's only one key for this srtp_session, and the cipher
   * supports key-sharing, then we assume that a new stream using
   * that key has just started up
  stream = srtp_get_stream(ctx, hdr->ssrc);
  if (stream == NULL) {
    if (ctx->stream_template != NULL) {
      srtp_stream_ctx_t *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 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;
    } else {
      /* no template stream, so we return an error */
      return err_status_no_ctx;
   * verify that stream is for sending 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.
  if (stream->direction != dir_srtp_sender) {
    if (stream->direction == dir_unknown) {
      stream->direction = dir_srtp_sender;
    } else {
      srtp_handle_event(ctx, stream, event_ssrc_collision);

  /* get tag length from stream context */
  tag_len = auth_get_tag_length(stream->rtcp_auth); 

   * set encryption start and encryption length - if we're not
   * providing confidentiality, set enc_start to NULL
  enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;  
  enc_octet_len = *pkt_octet_len - octets_in_rtcp_header;

  /* all of the packet, except the header, gets encrypted */
  /* NOTE: hdr->length is not usable - it refers to only the first
       RTCP report in the compound packet! */
  /* NOTE: trailer is 32-bit aligned because RTCP 'packets' are always
       multiples of 32-bits (RFC 3550 6.1) */
  trailer = (uint32_t *) ((char *)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 */    

   * 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); 

   * check sequence number for overruns, and copy it into the packet
   * if its value isn't too big
  status = rdb_increment(&stream->rtcp_rdb);
  if (status)
    return status;
  seq_num = rdb_get_value(&stream->rtcp_rdb);
  *trailer |= htonl(seq_num);
  debug_print(mod_srtp, "srtcp index: %x", seq_num);

   * if we're using rindael counter mode, set nonce and seq 
  if (stream->rtcp_cipher->type == &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 = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtcp_cipher->state, &iv);

  } 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 = cipher_set_iv(stream->rtcp_cipher, &iv);
  if (status)
    return err_status_cipher_fail;

   * if we're authenticating using a universal hash, put the keystream
   * prefix into the authentication tag
  /* if auth_start is non-null, then put keystream into tag  */
  if (auth_start) {

    /* put keystream prefix into auth_tag */
    prefix_len = auth_get_prefix_length(stream->rtcp_auth);    
    status = cipher_output(stream->rtcp_cipher, auth_tag, prefix_len);

    debug_print(mod_srtp, "keystream prefix: %s", 
            octet_string_hex_string(auth_tag, prefix_len));

    if (status)
      return err_status_cipher_fail;

  /* if we're encrypting, exor keystream into the message */
  if (enc_start) {
    status = cipher_encrypt(stream->rtcp_cipher, 
                      (uint8_t *)enc_start, &enc_octet_len);
    if (status)
      return err_status_cipher_fail;

  /* initialize auth func context */

   * run auth func over packet (including trailer), and write the
   * result at auth_tag 
  status = auth_compute(stream->rtcp_auth, 
                  (uint8_t *)auth_start, 
                  (*pkt_octet_len) + sizeof(srtcp_trailer_t), 
  debug_print(mod_srtp, "srtcp auth tag:    %s", 
            octet_string_hex_string(auth_tag, tag_len));
  if (status)
    return err_status_auth_fail;   
  /* increase the packet length by the length of the auth tag and seq_num*/
  *pkt_octet_len += (tag_len + sizeof(srtcp_trailer_t));
  return err_status_ok;  

Generated by  Doxygen 1.6.0   Back to index