⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srtp.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 4 页
字号:
  /* 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 */  auth_start(stream->rtcp_auth);  /*    * 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), 			auth_tag);  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;  }err_status_t srtp_unprotect_rtcp(srtp_t ctx, void *srtcp_hdr, int *pkt_octet_len) {  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      */  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     */  uint8_t tmp_tag[SRTP_MAX_TAG_LEN];  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) {      stream = ctx->stream_template;      debug_print(mod_srtp, "srtcp using provisional stream (SSRC: 0x%08x)", 		  hdr->ssrc);    } else {      /* no template stream, so we return an error */      return err_status_no_ctx;    }   }    /* get tag length from stream context */  tag_len = auth_get_tag_length(stream->rtcp_auth);   /*   * set encryption start, encryption length, and trailer   */  enc_octet_len = *pkt_octet_len -                   (octets_in_rtcp_header + tag_len + 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	 normal data. */  /* This would need to be modified for optional mikey data */  /*   * 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 -(tag_len + sizeof(srtcp_trailer_t)));  if (*((unsigned char *) trailer) & SRTCP_E_BYTE_BIT) {    enc_start = (uint32_t *)hdr + uint32s_in_rtcp_header;    } else {    enc_octet_len = 0;    enc_start = NULL; /* this indicates that there's no encryption */  }  /*    * set the auth_start and auth_tag pointers to the proper locations   * (note that srtcp *always* uses authentication, unlike srtp)   */  auth_start = (uint32_t *)hdr;  auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;  /*    * check the sequence number for replays   */  /* this is easier than dealing with bitfield access */  seq_num = ntohl(*trailer) & SRTCP_INDEX_MASK;  debug_print(mod_srtp, "srtcp index: %x", seq_num);  status = rdb_check(&stream->rtcp_rdb, seq_num);  if (status)    return status;  /*    * if we're using aes 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;  /* initialize auth func context */  auth_start(stream->rtcp_auth);  /* run auth func over packet, put result into tmp_tag */  status = auth_compute(stream->rtcp_auth, (uint8_t *)auth_start,  			*pkt_octet_len - tag_len,			tmp_tag);  debug_print(mod_srtp, "srtcp computed tag:       %s", 	      octet_string_hex_string(tmp_tag, tag_len));  if (status)    return err_status_auth_fail;       /* compare the tag just computed with the one in the packet */  debug_print(mod_srtp, "srtcp tag from packet:    %s", 	      octet_string_hex_string(auth_tag, tag_len));    if (octet_string_is_eq(tmp_tag, auth_tag, tag_len))    return err_status_auth_fail;  /*    * if we're authenticating using a universal hash, put the keystream   * prefix into the authentication tag   */  prefix_len = auth_get_prefix_length(stream->rtcp_auth);      if (prefix_len) {    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 decrypting, 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;  }  /* decrease the packet length by the length of the auth tag and seq_num*/  *pkt_octet_len -= (tag_len + sizeof(srtcp_trailer_t));  /*    * 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;  }  /* we've passed the authentication check, so add seq_num to the rdb */  rdb_add_index(&stream->rtcp_rdb, seq_num);          return err_status_ok;  }/* * dtls keying for srtp  */err_status_tcrypto_policy_set_from_profile_for_rtp(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:    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);    break;  case srtp_profile_aes128_cm_sha1_32:    crypto_policy_set_aes_cm_128_hmac_sha1_32(policy);    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);    break;  case srtp_profile_null_sha1_80:    crypto_policy_set_null_cipher_hmac_sha1_80(policy);    crypto_policy_set_null_cipher_hmac_sha1_80(policy);    break;    /* the following profiles are not (yet) supported */  case srtp_profile_null_sha1_32:  case srtp_profile_aes256_cm_sha1_80:  case srtp_profile_aes256_cm_sha1_32:  default:    return err_status_bad_param;  }  return err_status_ok;}err_status_tcrypto_policy_set_from_profile_for_rtcp(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:    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);    break;  case srtp_profile_aes128_cm_sha1_32:    crypto_policy_set_aes_cm_128_hmac_sha1_80(policy);    break;  case srtp_profile_null_sha1_80:    crypto_policy_set_null_cipher_hmac_sha1_80(policy);    break;    /* the following profiles are not (yet) supported */  case srtp_profile_null_sha1_32:  case srtp_profile_aes256_cm_sha1_80:  case srtp_profile_aes256_cm_sha1_32:  default:    return err_status_bad_param;  }  return err_status_ok;}voidappend_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 intsrtp_profile_get_master_key_length(srtp_profile_t profile) {  switch(profile) {  case srtp_profile_aes128_cm_sha1_80:    return 16;    break;  case srtp_profile_aes128_cm_sha1_32:    return 16;    break;  case srtp_profile_null_sha1_80:    return 16;    break;    /* the following profiles are not (yet) supported */  case srtp_profile_null_sha1_32:  case srtp_profile_aes256_cm_sha1_80:  case srtp_profile_aes256_cm_sha1_32:  default:    return 0;  /* indicate error by returning a zero */  }}unsigned intsrtp_profile_get_master_salt_length(srtp_profile_t profile) {  switch(profile) {  case srtp_profile_aes128_cm_sha1_80:    return 14;    break;  case srtp_profile_aes128_cm_sha1_32:    return 14;    break;  case srtp_profile_null_sha1_80:    return 14;    break;    /* the following profiles are not (yet) supported */  case srtp_profile_null_sha1_32:  case srtp_profile_aes256_cm_sha1_80:  case srtp_profile_aes256_cm_sha1_32:  default:    return 0;  /* indicate error by returning a zero */  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -