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

📄 srtp.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * srtp.c * * the secure real-time transport protocol * * David A. McGrew * Cisco Systems, Inc. *//* *	 * Copyright (c) 2001-2006, Cisco Systems, Inc. * All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  *   Redistributions of source code must retain the above copyright *   notice, this list of conditions and the following disclaimer. *  *   Redistributions in binary form must reproduce the above *   copyright notice, this list of conditions and the following *   disclaimer in the documentation and/or other materials provided *   with the distribution. *  *   Neither the name of the Cisco Systems, Inc. nor the names of its *   contributors may be used to endorse or promote products derived *   from this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */#include "srtp_priv.h"#include "aes_icm.h"         /* aes_icm is used in the KDF  */#include "alloc.h"           /* for crypto_alloc()          */#ifndef SRTP_KERNEL# include <limits.h># ifdef HAVE_NETINET_IN_H#  include <netinet/in.h># elif defined(HAVE_WINSOCK2_H)#  include <winsock2.h># endif#endif /* ! SRTP_KERNEL */extern cipher_type_t aes_icm;extern auth_type_t   tmmhv2;/* the debug module for srtp */debug_module_t mod_srtp = {  0,                  /* debugging is off by default */  "srtp"              /* printable name for module   */};#define octets_in_rtp_header   12#define uint32s_in_rtp_header  3#define octets_in_rtcp_header  8#define uint32s_in_rtcp_header 2err_status_tsrtp_stream_alloc(srtp_stream_ctx_t **str_ptr,		  const srtp_policy_t *p) {  srtp_stream_ctx_t *str;  err_status_t stat;  /*   * This function allocates the stream context, rtp and rtcp ciphers   * and auth functions, and key limit structure.  If there is a   * failure during allocation, we free all previously allocated   * memory and return a failure code.  The code could probably    * be improved, but it works and should be clear.   */  /* allocate srtp stream and set str_ptr */  str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));  if (str == NULL)    return err_status_alloc_fail;  *str_ptr = str;      /* allocate cipher */  stat = crypto_kernel_alloc_cipher(p->rtp.cipher_type, 				    &str->rtp_cipher, 				    p->rtp.cipher_key_len);   if (stat) {    crypto_free(str);    return stat;  }  /* allocate auth function */  stat = crypto_kernel_alloc_auth(p->rtp.auth_type, 				  &str->rtp_auth,				  p->rtp.auth_key_len, 				  p->rtp.auth_tag_len);   if (stat) {    cipher_dealloc(str->rtp_cipher);    crypto_free(str);    return stat;  }    /* allocate key limit structure */  str->limit = (key_limit_ctx_t*) crypto_alloc(sizeof(key_limit_ctx_t));  if (str->limit == NULL) {    auth_dealloc(str->rtp_auth);    cipher_dealloc(str->rtp_cipher);    crypto_free(str);     return err_status_alloc_fail;  }  /*   * ...and now the RTCP-specific initialization - first, allocate   * the cipher    */  stat = crypto_kernel_alloc_cipher(p->rtcp.cipher_type, 				    &str->rtcp_cipher, 				    p->rtcp.cipher_key_len);   if (stat) {    auth_dealloc(str->rtp_auth);    cipher_dealloc(str->rtp_cipher);    crypto_free(str->limit);    crypto_free(str);    return stat;  }  /* allocate auth function */  stat = crypto_kernel_alloc_auth(p->rtcp.auth_type, 				  &str->rtcp_auth,				  p->rtcp.auth_key_len, 				  p->rtcp.auth_tag_len);   if (stat) {    cipher_dealloc(str->rtcp_cipher);    auth_dealloc(str->rtp_auth);    cipher_dealloc(str->rtp_cipher);    crypto_free(str->limit);    crypto_free(str);   return stat;  }    return err_status_ok;}err_status_tsrtp_stream_dealloc(srtp_t session, srtp_stream_ctx_t *stream) {   err_status_t status;    /*   * we use a conservative deallocation strategy - if any deallocation   * fails, then we report that fact without trying to deallocate   * anything else   */  /* deallocate cipher, if it is not the same as that in template */  if (session->stream_template      && stream->rtp_cipher == session->stream_template->rtp_cipher) {    /* do nothing */  } else {    status = cipher_dealloc(stream->rtp_cipher);     if (status)       return status;  }  /* deallocate auth function, if it is not the same as that in template */  if (session->stream_template      && stream->rtp_auth == session->stream_template->rtp_auth) {    /* do nothing */  } else {    status = auth_dealloc(stream->rtp_auth);    if (status)      return status;  }  /* deallocate key usage limit, if it is not the same as that in template */  if (session->stream_template      && stream->limit == session->stream_template->limit) {    /* do nothing */  } else {    crypto_free(stream->limit);  }     /*    * deallocate rtcp cipher, if it is not the same as that in   * template    */  if (session->stream_template      && stream->rtcp_cipher == session->stream_template->rtcp_cipher) {    /* do nothing */  } else {    status = cipher_dealloc(stream->rtcp_cipher);     if (status)       return status;  }  /*   * deallocate rtcp auth function, if it is not the same as that in   * template    */  if (session->stream_template      && stream->rtcp_auth == session->stream_template->rtcp_auth) {    /* do nothing */  } else {    status = auth_dealloc(stream->rtcp_auth);    if (status)      return status;  }    /* deallocate srtp stream context */  crypto_free(stream);  return err_status_ok;}/* * srtp_stream_clone(stream_template, new) allocates a new stream and * initializes it using the cipher and auth of the stream_template *  * the only unique data in a cloned stream is the replay database and * the SSRC */err_status_tsrtp_stream_clone(const srtp_stream_ctx_t *stream_template, 		  uint32_t ssrc, 		  srtp_stream_ctx_t **str_ptr) {  err_status_t status;  srtp_stream_ctx_t *str;  debug_print(mod_srtp, "cloning stream (SSRC: 0x%08x)", ssrc);  /* allocate srtp stream and set str_ptr */  str = (srtp_stream_ctx_t *) crypto_alloc(sizeof(srtp_stream_ctx_t));  if (str == NULL)    return err_status_alloc_fail;  *str_ptr = str;    /* set cipher and auth pointers to those of the template */  str->rtp_cipher  = stream_template->rtp_cipher;  str->rtp_auth    = stream_template->rtp_auth;  str->rtcp_cipher = stream_template->rtcp_cipher;  str->rtcp_auth   = stream_template->rtcp_auth;  /* set key limit to point to that of the template */  status = key_limit_clone(stream_template->limit, &str->limit);  if (status)     return status;  /* initialize replay databases */  rdbx_init(&str->rtp_rdbx);  rdb_init(&str->rtcp_rdb);    /* set ssrc to that provided */  str->ssrc = ssrc;  /* set direction and security services */  str->direction     = stream_template->direction;  str->rtp_services  = stream_template->rtp_services;  str->rtcp_services = stream_template->rtcp_services;  /* defensive coding */  str->next = NULL;  return err_status_ok;}/* * key derivation functions, internal to libSRTP * * srtp_kdf_t is a key derivation context * * srtp_kdf_init(&kdf, k) initializes kdf with the key k *  * srtp_kdf_generate(&kdf, l, kl, keylen) derives the key * corresponding to label l and puts it into kl; the length * of the key in octets is provided as keylen.  this function * should be called once for each subkey that is derived. * * srtp_kdf_clear(&kdf) zeroizes the kdf state */typedef enum {  label_rtp_encryption  = 0x00,  label_rtp_msg_auth    = 0x01,  label_rtp_salt        = 0x02,  label_rtcp_encryption = 0x03,  label_rtcp_msg_auth   = 0x04,  label_rtcp_salt       = 0x05} srtp_prf_label;/* * srtp_kdf_t represents a key derivation function.  The SRTP * default KDF is the only one implemented at present. */typedef struct {   aes_icm_ctx_t c;    /* cipher used for key derivation  */  } srtp_kdf_t;err_status_tsrtp_kdf_init(srtp_kdf_t *kdf, const uint8_t key[30]) {  aes_icm_context_init(&kdf->c, key);  return err_status_ok;}err_status_tsrtp_kdf_generate(srtp_kdf_t *kdf, srtp_prf_label label,		  uint8_t *key, int length) {  v128_t nonce;    /* set eigth octet of nonce to <label>, set the rest of it to zero */  v128_set_to_zero(&nonce);  nonce.v8[7] = label;   aes_icm_set_iv(&kdf->c, &nonce);      /* generate keystream output */  aes_icm_output(&kdf->c, key, length);  return err_status_ok;}err_status_tsrtp_kdf_clear(srtp_kdf_t *kdf) {    /* zeroize aes context */  octet_string_set_to_zero((uint8_t *)kdf, sizeof(srtp_kdf_t));  return err_status_ok;  }/* *  end of key derivation functions  */#define MAX_SRTP_KEY_LEN 256err_status_tsrtp_stream_init_keys(srtp_stream_ctx_t *srtp, const void *key) {  err_status_t stat;  srtp_kdf_t kdf;  uint8_t tmp_key[MAX_SRTP_KEY_LEN];    /* initialize KDF state     */  srtp_kdf_init(&kdf, (const uint8_t *)key);    /* generate encryption key  */  srtp_kdf_generate(&kdf, label_rtp_encryption, 		    tmp_key, cipher_get_key_length(srtp->rtp_cipher));  /*    * if the cipher in the srtp context is aes_icm, then we need   * to generate the salt value   */  if (srtp->rtp_cipher->type == &aes_icm) {    /* FIX!!! this is really the cipher key length; rest is salt */    int base_key_len = 16;    int salt_len = cipher_get_key_length(srtp->rtp_cipher) - base_key_len;        debug_print(mod_srtp, "found aes_icm, generating salt", NULL);    /* generate encryption salt, put after encryption key */    srtp_kdf_generate(&kdf, label_rtp_salt, 		      tmp_key + base_key_len, salt_len);  }  debug_print(mod_srtp, "cipher key: %s", 	      octet_string_hex_string(tmp_key, 		      cipher_get_key_length(srtp->rtp_cipher)));    /* initialize cipher */  stat = cipher_init(srtp->rtp_cipher, tmp_key, direction_any);  if (stat) {    /* zeroize temp buffer */    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);    return err_status_init_fail;  }  /* generate authentication key */  srtp_kdf_generate(&kdf, label_rtp_msg_auth,		    tmp_key, auth_get_key_length(srtp->rtp_auth));  debug_print(mod_srtp, "auth key:   %s",	      octet_string_hex_string(tmp_key, 				      auth_get_key_length(srtp->rtp_auth)));   /* initialize auth function */  stat = auth_init(srtp->rtp_auth, tmp_key);  if (stat) {    /* zeroize temp buffer */    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);    return err_status_init_fail;  }  /*   * ...now initialize SRTCP keys   */  /* generate encryption key  */  srtp_kdf_generate(&kdf, label_rtcp_encryption, 		    tmp_key, cipher_get_key_length(srtp->rtcp_cipher));  /*    * if the cipher in the srtp context is aes_icm, then we need   * to generate the salt value   */  if (srtp->rtcp_cipher->type == &aes_icm) {    /* FIX!!! this is really the cipher key length; rest is salt */    int base_key_len = 16;    int salt_len = cipher_get_key_length(srtp->rtcp_cipher) - base_key_len;    debug_print(mod_srtp, "found aes_icm, generating rtcp salt", NULL);    /* generate encryption salt, put after encryption key */    srtp_kdf_generate(&kdf, label_rtcp_salt, 		      tmp_key + base_key_len, salt_len);  }  debug_print(mod_srtp, "rtcp cipher key: %s", 	      octet_string_hex_string(tmp_key, 		   cipher_get_key_length(srtp->rtcp_cipher)));    /* initialize cipher */  stat = cipher_init(srtp->rtcp_cipher, tmp_key, direction_any);  if (stat) {    /* zeroize temp buffer */    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);    return err_status_init_fail;  }  /* generate authentication key */  srtp_kdf_generate(&kdf, label_rtcp_msg_auth,		    tmp_key, auth_get_key_length(srtp->rtcp_auth));  debug_print(mod_srtp, "rtcp auth key:   %s",	      octet_string_hex_string(tmp_key, 		     auth_get_key_length(srtp->rtcp_auth)));   /* initialize auth function */  stat = auth_init(srtp->rtcp_auth, tmp_key);  if (stat) {    /* zeroize temp buffer */    octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);    return err_status_init_fail;  }  /* clear memory then return */  srtp_kdf_clear(&kdf);  octet_string_set_to_zero(tmp_key, MAX_SRTP_KEY_LEN);    return err_status_ok;}err_status_tsrtp_stream_init(srtp_stream_ctx_t *srtp, 		  const srtp_policy_t *p) {  err_status_t err;   debug_print(mod_srtp, "initializing stream (SSRC: 0x%08x)", 	       p->ssrc.value);   /* initialize replay database */   rdbx_init(&srtp->rtp_rdbx);

⌨️ 快捷键说明

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