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

📄 srtp.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 4 页
字号:
   /* initialize key limit to maximum value */#ifdef NO_64BIT_MATH{   uint64_t temp;   temp = make64(UINT_MAX,UINT_MAX);   key_limit_set(srtp->limit, temp);}#else   key_limit_set(srtp->limit, 0xffffffffffffLL);#endif   /* set the SSRC value */   srtp->ssrc = htonl(p->ssrc.value);   /* set the security service flags */   srtp->rtp_services  = p->rtp.sec_serv;   srtp->rtcp_services = p->rtcp.sec_serv;   /*    * set direction to unknown - this flag gets checked in srtp_protect(),    * srtp_unprotect(), srtp_protect_rtcp(), and srtp_unprotect_rtcp(), and     * gets set appropriately if it is set to unknown.    */   srtp->direction = dir_unknown;   /* initialize SRTCP replay database */   rdb_init(&srtp->rtcp_rdb);   /* DAM - no RTCP key limit at present */   /* initialize keys */   err = srtp_stream_init_keys(srtp, p->key);   if (err) return err;   return err_status_ok;   } /*  * srtp_event_reporter is an event handler function that merely  * reports the events that are reported by the callbacks  */ void srtp_event_reporter(srtp_event_data_t *data) {   err_report(err_level_warning, "srtp: in stream 0x%x: ", 	      data->stream->ssrc);   switch(data->event) {   case event_ssrc_collision:     err_report(err_level_warning, "\tSSRC collision\n");     break;   case event_key_soft_limit:     err_report(err_level_warning, "\tkey usage soft limit reached\n");     break;   case event_key_hard_limit:     err_report(err_level_warning, "\tkey usage hard limit reached\n");     break;   case event_packet_index_limit:     err_report(err_level_warning, "\tpacket index limit reached\n");     break;   default:     err_report(err_level_warning, "\tunknown event reported to handler\n");   } } /*  * srtp_event_handler is a global variable holding a pointer to the  * event handler function; this function is called for any unexpected  * event that needs to be handled out of the SRTP data path.  see  * srtp_event_t in srtp.h for more info  *  * it is okay to set srtp_event_handler to NULL, but we set   * it to the srtp_event_reporter.  */ static srtp_event_handler_func_t *srtp_event_handler = srtp_event_reporter; err_status_t srtp_install_event_handler(srtp_event_handler_func_t func) {   /*     * note that we accept NULL arguments intentionally - calling this    * function with a NULL arguments removes an event handler that's    * been previously installed    */   /* set global event handling function */   srtp_event_handler = func;   return err_status_ok; } err_status_t srtp_protect(srtp_ctx_t *ctx, void *rtp_hdr, int *pkt_octet_len) {   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      */   unsigned enc_octet_len = 0; /* number of octets in encrypted portion  */   xtd_seq_num_t est;          /* estimated xtd_seq_num_t of *hdr        */   int delta;                  /* delta of local pkt idx and that in hdr */   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;   debug_print(mod_srtp, "function srtp_protect", NULL);  /* we assume the hdr is 32-bit aligned to start */   /* check the packet length - it must at least contain a full header */   if (*pkt_octet_len < octets_in_rtp_header)     return err_status_bad_param;   /*    * 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 a template 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 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 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);     }   }  /*    * 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;  }   /* get tag length from stream */   tag_len = auth_get_tag_length(stream->rtp_auth);    /*    * find starting point for encryption and length of data to be    * encrypted - the encrypted portion starts after the rtp header    * extension, if present; otherwise, it starts after the last csrc,    * if any are present    *    * if we're not providing confidentiality, set enc_start to NULL    */   if (stream->rtp_services & sec_serv_conf) {     enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;       if (hdr->x == 1) {       srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;       enc_start += (ntohs(xtn_hdr->length) + 1);     }     enc_octet_len = (unsigned int)(*pkt_octet_len 				    - ((enc_start - (uint32_t *)hdr) << 2));   } else {     enc_start = NULL;   }   /*     * if we're providing authentication, set the auth_start and auth_tag    * pointers to the proper locations; otherwise, set auth_start to NULL    * to indicate that no authentication is needed    */   if (stream->rtp_services & sec_serv_auth) {     auth_start = (uint32_t *)hdr;     auth_tag = (uint8_t *)hdr + *pkt_octet_len;   } else {     auth_start = NULL;     auth_tag = NULL;   }   /*    * estimate the packet index using the start of the replay window       * and the sequence number from the header    */   delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));   status = rdbx_check(&stream->rtp_rdbx, delta);   if (status)     return status;  /* we've been asked to reuse an index */   rdbx_add_index(&stream->rtp_rdbx, delta);#ifdef NO_64BIT_MATH   debug_print2(mod_srtp, "estimated packet index: %08x%08x", 		high32(est),low32(est));#else   debug_print(mod_srtp, "estimated packet index: %016llx", est);#endif   /*     * if we're using rindael counter mode, set nonce and seq     */   if (stream->rtp_cipher->type == &aes_icm) {     v128_t iv;     iv.v32[0] = 0;     iv.v32[1] = hdr->ssrc;#ifdef NO_64BIT_MATH     iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),								 low32(est) << 16));#else     iv.v64[1] = be64_to_cpu(est << 16);#endif     status = cipher_set_iv(stream->rtp_cipher, &iv);   } else {       v128_t iv;     /* 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 = cipher_set_iv(stream->rtp_cipher, &iv);   }   if (status)     return 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      /*     * if we're authenticating using a universal hash, put the keystream    * prefix into the authentication tag    */   if (auth_start) {         prefix_len = auth_get_prefix_length(stream->rtp_auth);        if (prefix_len) {      status = cipher_output(stream->rtp_cipher, auth_tag, prefix_len);      if (status)	return err_status_cipher_fail;      debug_print(mod_srtp, "keystream prefix: %s", 		  octet_string_hex_string(auth_tag, prefix_len));    }  }  /* if we're encrypting, exor keystream into the message */  if (enc_start) {    status = cipher_encrypt(stream->rtp_cipher, 			    (uint8_t *)enc_start, &enc_octet_len);    if (status)      return err_status_cipher_fail;  }  /*   *  if we're authenticating, run authentication function and put result   *  into the auth_tag    */  if (auth_start) {            /* initialize auth func context */    status = auth_start(stream->rtp_auth);    if (status) return status;    /* run auth func over packet */    status = auth_update(stream->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 = auth_compute(stream->rtp_auth, (uint8_t *)&est, 4, auth_tag);     debug_print(mod_srtp, "srtp auth tag:    %s", 		octet_string_hex_string(auth_tag, tag_len));    if (status)      return err_status_auth_fail;     }  if (auth_tag) {    /* increase the packet length by the length of the auth tag */    *pkt_octet_len += tag_len;  }  return err_status_ok;  }err_status_tsrtp_unprotect(srtp_ctx_t *ctx, void *srtp_hdr, int *pkt_octet_len) {  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      */  unsigned enc_octet_len = 0;/* number of octets in encrypted portion */  uint8_t *auth_tag = NULL; /* location of auth_tag within packet     */  xtd_seq_num_t est;        /* estimated xtd_seq_num_t of *hdr        */  int delta;                /* delta of local pkt idx and that in hdr */  v128_t iv;  err_status_t status;  srtp_stream_ctx_t *stream;  uint8_t tmp_tag[SRTP_MAX_TAG_LEN];  int tag_len, prefix_len;  debug_print(mod_srtp, "function srtp_unprotect", NULL);  /* we assume the hdr is 32-bit aligned to start */  /* check the packet length - it must at least contain a full header */  if (*pkt_octet_len < octets_in_rtp_header)    return err_status_bad_param;  /*   * 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, "using provisional stream (SSRC: 0x%08x)",		  hdr->ssrc);            /*        * set estimated packet index to sequence number from header,       * and set delta equal to the same value       */#ifdef NO_64BIT_MATH      est = (xtd_seq_num_t) make64(0,ntohs(hdr->seq));      delta = low32(est);#else      est = (xtd_seq_num_t) ntohs(hdr->seq);      delta = (int)est;#endif    } else {            /*       * no stream corresponding to SSRC found, and we don't do       * key-sharing, so return an error       */      return err_status_no_ctx;    }  } else {      /* estimate packet index from seq. num. in header */    delta = rdbx_estimate_index(&stream->rtp_rdbx, &est, ntohs(hdr->seq));        /* check replay database */    status = rdbx_check(&stream->rtp_rdbx, delta);    if (status)      return status;  }#ifdef NO_64BIT_MATH  debug_print2(mod_srtp, "estimated u_packet index: %08x%08x", high32(est),low32(est));#else  debug_print(mod_srtp, "estimated u_packet index: %016llx", est);#endif  /* get tag length from stream */  tag_len = auth_get_tag_length(stream->rtp_auth);   /*    * set the cipher's IV properly, depending on whatever cipher we   * happen to be using   */  if (stream->rtp_cipher->type == &aes_icm) {    /* aes counter mode */    iv.v32[0] = 0;    iv.v32[1] = hdr->ssrc;  /* still in network order */#ifdef NO_64BIT_MATH    iv.v64[1] = be64_to_cpu(make64((high32(est) << 16) | (low32(est) >> 16),			         low32(est) << 16));#else    iv.v64[1] = be64_to_cpu(est << 16);#endif    status = aes_icm_set_iv((aes_icm_ctx_t*)stream->rtp_cipher->state, &iv);  } else {          /* no particular format - set the iv to the pakcet index */  #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 = cipher_set_iv(stream->rtp_cipher, &iv);  }  if (status)    return 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  /*   * find starting point for decryption and length of data to be   * decrypted - the encrypted portion starts after the rtp header   * extension, if present; otherwise, it starts after the last csrc,   * if any are present   *   * if we're not providing confidentiality, set enc_start to NULL   */  if (stream->rtp_services & sec_serv_conf) {    enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;      if (hdr->x == 1) {      srtp_hdr_xtnd_t *xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;      enc_start += (ntohs(xtn_hdr->length) + 1);    }      enc_octet_len = (uint32_t)(*pkt_octet_len - tag_len 			       - ((enc_start - (uint32_t *)hdr) << 2));  } else {    enc_start = NULL;  }  /*    * if we're providing authentication, set the auth_start and auth_tag   * pointers to the proper locations; otherwise, set auth_start to NULL   * to indicate that no authentication is needed   */  if (stream->rtp_services & sec_serv_auth) {    auth_start = (uint32_t *)hdr;    auth_tag = (uint8_t *)hdr + *pkt_octet_len - tag_len;

⌨️ 快捷键说明

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