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

📄 ust.c

📁 srtp-1.3.20 security RTP source
💻 C
字号:
/* * ust.c * * C implementation of the universal security transform * * David A. McGrew * Cisco Systems, Inc. *//* *	 * Copyright (c) 2001-2004, 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 "ust.h"debug_module_t mod_ust = {  0,                 /* debugging is off by default */  "ust"              /* printable module name       */};err_status_tust_alloc(ust_ctx_t *ctx,            /* ust context                       */         cipher_type_id_t c_id,      /* keystream generator identifier    */	 int cipher_key_len,         /* number of octets in cipher key    */	 auth_type_id_t a_id,        /* auth algorithm identifier         */	 int auth_key_len,           /* number of octets in the auth key  */	 int auth_tag_len,           /* number of octets in the auth tag  */	 int replay_window_len       /* bits in replay window (0 == none) */	 ) {  err_status_t stat;  debug_print(mod_ust, "allocating context", NULL);  /* check replay_window_len to see if we can support the value requested */  if (replay_window_len != 128)    return err_status_bad_param;  /* allocate cipher */  stat = crypto_kernel_alloc_cipher(c_id, &ctx->c, cipher_key_len);   if (stat)    return err_status_alloc_fail;  /* allocate auth function */  stat = crypto_kernel_alloc_auth(a_id, &ctx->h, auth_key_len, auth_tag_len);   if (stat) {    cipher_dealloc(ctx->c);    return err_status_alloc_fail;  }    /* allocate storage for the authentication tag */  ctx->auth_tag = (octet_t *)xalloc(auth_tag_len);  if (ctx->auth_tag == NULL) {    cipher_dealloc(ctx->c);    auth_dealloc(ctx->h);    return err_status_alloc_fail;      }    return err_status_ok;}err_status_tust_init(ust_ctx_t *ctx, octet_t *cipher_key, octet_t *auth_key) {  err_status_t stat;  v128_t zero;  debug_print(mod_ust, "initializing context", NULL);  /* initialize cipher */  stat = cipher_init(ctx->c, cipher_key);  if (stat)     return err_status_init_fail;  /*  initialize auth function  */    if (auth_key == NULL) {    octet_t *buffer;        /*      * we need to generate the authentication key using the UST     * default method (using keystream segment number zero)     */    v128_set_to_zero(&zero);    stat = cipher_set_iv(ctx->c, &zero);    if (stat)      return stat;        buffer = (octet_t *)xalloc(auth_get_key_length(ctx->h));    if (buffer == NULL)      return err_status_init_fail;    stat = cipher_output(ctx->c, buffer, auth_get_key_length(ctx->h));    xfree(buffer);    if (stat)      return stat;  }      stat = auth_init(ctx->h, auth_key);  if (stat)     return err_status_init_fail;  return err_status_ok;}/* * the ust_xfm function  * * ctx is the ust context, which holds the cipher and hash function * keys and parameters, as well as anti-replay information *  * idx is the packet index, a 64-bit unsigned integer which  * should be unique for each invocation of ust_xfm for a * given ctx *  * if auth_start != NULL, then authentication is provided to the * auth_len octets of data at auth_start by computing the * authentication tag and writing it to *tag; otherwise, the * authentication tag is not computed * * if enc_start != NULL, then encryption is provided to the * enc_len octets of data at enc_start by exoring keystream * into that data; otherwise, no encryption is done * * tag points to the authentication tag; after ust_xfm returns, * it contains the tag corresonding to the data at auth_start * (if auth_start != NULL) -- note that there MUST be at least * ust_tag_len(ctx) octets of storage at *tag!  */err_status_tust_xfm(ust_ctx_t *ctx,      /* ust context                      */	xtd_seq_num_t idx,   /* index                            */	octet_t *enc_start,  /* pointer to encryption start      */	int enc_len,         /* number of octets to encrypt      */	octet_t *auth_start, /* pointer to authentication start  */	int auth_len,        /* number of octets to authenticate */	octet_t *tag         /* authentication tag               */	) {  int stat;  int prefix_len = auth_get_prefix_length(ctx->h);  v128_t nonce;  /* set the index to idx */    nonce.v64[0] = 0;  nonce.v64[1] = idx;  stat = cipher_set_iv(ctx->c, &nonce);  if (stat)    return err_status_cipher_fail;  /* if auth_start is non-null, then put keystream into tag  */  if (auth_start) {        /* zeroize tag, then add in keystream */    octet_string_set_to_zero(tag, prefix_len);    stat = cipher_output(ctx->c, tag, prefix_len);     debug_print(mod_ust, "ust_xfm prefix: %s", 		octet_string_hex_string(tag, prefix_len));    if (stat)      return err_status_cipher_fail;  }  /* if enc_start is non-null, encrypt data */  if (enc_start) {    stat = cipher_encrypt(ctx->c, enc_start, &enc_len);    if (stat)      return err_status_cipher_fail;  }  /* if auth_start is non-null, authenticate message */  if (auth_start) {    stat = auth_compute(ctx->h, auth_start, auth_len, tag);    debug_print(mod_ust, "ust_xfm tag:    %s", 		octet_string_hex_string(tag, prefix_len));    if (stat)      return err_status_auth_fail;  }  return err_status_ok;}/* * the ust_inv_xfm function (ust inverse transform) * * ctx is the ust context, which holds the cipher and hash function * keys and parameters, as well as anti-replay information *  * idx is the packet index, a 64-bit unsigned integer which  * should be unique for each invocation of ust_xfm for a * given ctx *  * if auth_start != NULL, then authentication is expected on the * auth_len octets of data at auth_start by computing the * authentication tag and comparing it to the value at *tag; * otherwise, no authentication check is performed * * if enc_start != NULL, then decryption is done to the enc_len * octets of data at enc_start by exoring keystream into that data; * otherwise, no decryption is done * * tag points to the authentication tag;  if auth_start != NULL, * then *tag is expected to hold the authentication tag corresponding * to the data at *auth_start -- note that there MUST be at least * ust_tag_len(ctx) octets of readable data at *tag!  */err_status_tust_inv_xfm(ust_ctx_t *ctx,      /* ust context                      */	    xtd_seq_num_t idx,   /* index                            */	    octet_t *enc_start,  /* pointer to encryption start      */	    int enc_len,         /* number of octets to encrypt      */	    octet_t *auth_start, /* pointer to authentication start  */	    int auth_len,        /* number of octets to authenticate */	    octet_t *tag         /* authentication tag               */	    ) {  int stat;  v128_t nonce;  /* set the index to idx */    nonce.v64[0] = 0;  nonce.v64[1] = idx;  stat = cipher_set_iv(ctx->c, &nonce);  if (stat)    return err_status_cipher_fail;  /*   * if auth_start is non-null, then put keystream into tag in ctx,   * compute auth_tag and compare to tag   */  if (auth_start) {        /* zeroize tag, then add in keystream */    stat = cipher_output(ctx->c, ctx->auth_tag, ctx->h->out_len);    debug_print(mod_ust, "ust_inv_xfm prefix: %s", 		octet_string_hex_string(ctx->auth_tag, ctx->h->out_len));    if (stat)      return err_status_cipher_fail;     /* compute hash then compare to tag value */    stat = auth_compute(ctx->h, auth_start, auth_len, ctx->auth_tag);    if (stat)      return err_status_auth_fail;    debug_print(mod_ust, "ust_inv_xfm tag:    %s",  	   octet_string_hex_string(ctx->auth_tag, ctx->h->out_len));    debug_print(mod_ust, "tag expected:       %s", 	   octet_string_hex_string(tag, ctx->h->out_len));    if (octet_string_is_eq(ctx->auth_tag, tag, ctx->h->out_len)) {      return err_status_auth_fail;    }  }  /* if enc_start is non-null, decrypt data */  if (enc_start) {    stat = cipher_encrypt(ctx->c, enc_start, &enc_len);    if (stat)      return err_status_cipher_fail;  }  return err_status_ok;}/*  * ust_xfm_u16() * * implements the ust transform with 16-bit explicit seq num */err_status_tust_xfm_u16(ust_ptr_t ctx,       /* pointer to ust context           */	    uint16_t idx,        /* index                            */	    octet_t *enc_start,  /* pointer to encryption start      */	    int enc_len,         /* number of octets to encrypt      */	    octet_t *auth_start, /* pointer to authentication start  */	    int auth_len,        /* number of octets to authenticate */	    octet_t *tag         /* authentication tag               */	    ) {  xtd_seq_num_t est;        /* estimated xtd_seq_num_t of *hdr        */  int delta;                /* delta of local pkt idx and that in hdr */  err_status_t status;  /*   * estimate the packet index using the start of the replay window      * and the sequence number from the header   */  delta = rdbx_estimate_index(&ctx->rdbx, &est, idx);  status = rdbx_check(&ctx->rdbx, delta);  if (status)    return status;  /* we've been asked to reuse an index */  rdbx_add_index(&ctx->rdbx, delta);   /* now apply crypto transform */  status = ust_xfm(ctx,        /* ust context                      */		   est,        /* 64-bit implicit seq num          */		   enc_start,  /* pointer to encryption start      */		   enc_len,    /* number of octets to encrypt      */		   auth_start, /* pointer to authentication start  */		   auth_len,   /* number of octets to authenticate */		   tag         /* authentication tag               */		   );  if (status)    return status;  /* add index into rdbx */  rdbx_add_index(&ctx->rdbx, delta);    return err_status_ok;}/* * ust_inv_xfm_u16() *  * implements inverse transform with 16-bit explicit seq num */err_status_tust_inv_xfm_u16(	ust_ctx_t *ctx,      /* ust context                        */	uint16_t seq,        /* 16-bit explicit seq num            */	octet_t *enc_start,  /* pointer to encryption start        */	int enc_len,         /* number of octets to encrypt        */	octet_t *auth_start, /* pointer to authentication start    */	int auth_len,        /* number of octets to authenticate   */	octet_t *tag         /* authentication tag                 */	) {  int delta;                /* delta of local pkt idx and that in hdr */  xtd_seq_num_t est;        /* estimated xtd_seq_num_t                */  err_status_t status;  /*   * estimate the packet index using the start of the replay window      * and the sequence number from the header   */  delta = rdbx_estimate_index(&ctx->rdbx, &est, seq);  status = rdbx_check(&ctx->rdbx, delta);  if (status)     return status;    status = ust_inv_xfm(ctx,        /* ust context                      */		       est,        /* 64-bit implicit seq num          */		       enc_start,  /* pointer to encryption start      */		       enc_len,    /* number of octets to encrypt      */		       auth_start, /* pointer to authentication start  */		       auth_len,   /* number of octets to authenticate */		       tag         /* authentication tag               */		       );  if (status)    return status;  /* add index into rdbx */  rdbx_add_index(&ctx->rdbx, delta);  return err_status_ok;}/* * ust_get_tag_len(ctx) returns the length (in octets) of the * authentication tag for the ust context ctx. * * this function can be used to determine the storage * space required to hold a particular tag, if need be */inline unsigned int ust_get_tag_len(ust_ctx_t *ctx) {  return ctx->h->out_len;}

⌨️ 快捷键说明

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