1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Upgrade libsrtp from 2.0.0 to 2.3.0, with source code. 4.0.79

This commit is contained in:
winlin 2021-03-02 14:29:06 +08:00
parent 3749d4d833
commit 8089fc004c
111 changed files with 45307 additions and 5 deletions

View file

@ -0,0 +1,101 @@
/*
* alloc.c
*
* memory allocation and deallocation
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "alloc.h"
#include "crypto_kernel.h"
/* the debug module for memory allocation */
srtp_debug_module_t srtp_mod_alloc = {
0, /* debugging is off by default */
"alloc" /* printable name for module */
};
/*
* Nota bene: the debugging statements for srtp_crypto_alloc() and
* srtp_crypto_free() have identical prefixes, which include the addresses
* of the memory locations on which they are operating. This fact can
* be used to locate memory leaks, by turning on memory debugging,
* grepping for 'alloc', then matching alloc and free calls by
* address.
*/
#if defined(HAVE_STDLIB_H)
void *srtp_crypto_alloc(size_t size)
{
void *ptr;
if (!size) {
return NULL;
}
ptr = calloc(1, size);
if (ptr) {
debug_print(srtp_mod_alloc, "(location: %p) allocated", ptr);
} else {
debug_print(srtp_mod_alloc, "allocation failed (asked for %zu bytes)\n",
size);
}
return ptr;
}
void srtp_crypto_free(void *ptr)
{
debug_print(srtp_mod_alloc, "(location: %p) freed", ptr);
free(ptr);
}
#else /* we need to define our own memory allocation routines */
#error no memory allocation defined yet
#endif

View file

@ -0,0 +1,561 @@
/*
* crypto_kernel.c
*
* header for the cryptographic kernel
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "alloc.h"
#include "crypto_kernel.h"
#include "cipher_types.h"
/* the debug module for the crypto_kernel */
srtp_debug_module_t srtp_mod_crypto_kernel = {
0, /* debugging is off by default */
"crypto kernel" /* printable name for module */
};
/* crypto_kernel is a global variable, the only one of its datatype */
srtp_crypto_kernel_t crypto_kernel = {
srtp_crypto_kernel_state_insecure, /* start off in insecure state */
NULL, /* no cipher types yet */
NULL, /* no auth types yet */
NULL /* no debug modules yet */
};
#define MAX_RNG_TRIALS 25
srtp_err_status_t srtp_crypto_kernel_init()
{
srtp_err_status_t status;
/* check the security state */
if (crypto_kernel.state == srtp_crypto_kernel_state_secure) {
/*
* we're already in the secure state, but we've been asked to
* re-initialize, so we just re-run the self-tests and then return
*/
return srtp_crypto_kernel_status();
}
/* initialize error reporting system */
status = srtp_err_reporting_init();
if (status) {
return status;
}
/* load debug modules */
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_crypto_kernel);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_auth);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_cipher);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_stat);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_alloc);
if (status) {
return status;
}
/* load cipher types */
status = srtp_crypto_kernel_load_cipher_type(&srtp_null_cipher,
SRTP_NULL_CIPHER);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_128,
SRTP_AES_ICM_128);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_256,
SRTP_AES_ICM_256);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_aes_icm);
if (status) {
return status;
}
#ifdef GCM
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_icm_192,
SRTP_AES_ICM_192);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_128,
SRTP_AES_GCM_128);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_cipher_type(&srtp_aes_gcm_256,
SRTP_AES_GCM_256);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_aes_gcm);
if (status) {
return status;
}
#endif
/* load auth func types */
status = srtp_crypto_kernel_load_auth_type(&srtp_null_auth, SRTP_NULL_AUTH);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_auth_type(&srtp_hmac, SRTP_HMAC_SHA1);
if (status) {
return status;
}
status = srtp_crypto_kernel_load_debug_module(&srtp_mod_hmac);
if (status) {
return status;
}
/* change state to secure */
crypto_kernel.state = srtp_crypto_kernel_state_secure;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_status()
{
srtp_err_status_t status;
srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
/* for each cipher type, describe and test */
while (ctype != NULL) {
srtp_err_report(srtp_err_level_info, "cipher: %s\n",
ctype->cipher_type->description);
srtp_err_report(srtp_err_level_info, " self-test: ");
status = srtp_cipher_type_self_test(ctype->cipher_type);
if (status) {
srtp_err_report(srtp_err_level_error, "failed with error code %d\n",
status);
exit(status);
}
srtp_err_report(srtp_err_level_info, "passed\n");
ctype = ctype->next;
}
/* for each auth type, describe and test */
while (atype != NULL) {
srtp_err_report(srtp_err_level_info, "auth func: %s\n",
atype->auth_type->description);
srtp_err_report(srtp_err_level_info, " self-test: ");
status = srtp_auth_type_self_test(atype->auth_type);
if (status) {
srtp_err_report(srtp_err_level_error, "failed with error code %d\n",
status);
exit(status);
}
srtp_err_report(srtp_err_level_info, "passed\n");
atype = atype->next;
}
srtp_crypto_kernel_list_debug_modules();
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_list_debug_modules()
{
srtp_kernel_debug_module_t *dm = crypto_kernel.debug_module_list;
/* describe each debug module */
srtp_err_report(srtp_err_level_info, "debug modules loaded:\n");
while (dm != NULL) {
srtp_err_report(srtp_err_level_info, " %s ", dm->mod->name);
if (dm->mod->on) {
srtp_err_report(srtp_err_level_info, "(on)\n");
} else {
srtp_err_report(srtp_err_level_info, "(off)\n");
}
dm = dm->next;
}
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_shutdown()
{
/*
* free dynamic memory used in crypto_kernel at present
*/
/* walk down cipher type list, freeing memory */
while (crypto_kernel.cipher_type_list != NULL) {
srtp_kernel_cipher_type_t *ctype = crypto_kernel.cipher_type_list;
crypto_kernel.cipher_type_list = ctype->next;
debug_print(srtp_mod_crypto_kernel, "freeing memory for cipher %s",
ctype->cipher_type->description);
srtp_crypto_free(ctype);
}
/* walk down authetication module list, freeing memory */
while (crypto_kernel.auth_type_list != NULL) {
srtp_kernel_auth_type_t *atype = crypto_kernel.auth_type_list;
crypto_kernel.auth_type_list = atype->next;
debug_print(srtp_mod_crypto_kernel,
"freeing memory for authentication %s",
atype->auth_type->description);
srtp_crypto_free(atype);
}
/* walk down debug module list, freeing memory */
while (crypto_kernel.debug_module_list != NULL) {
srtp_kernel_debug_module_t *kdm = crypto_kernel.debug_module_list;
crypto_kernel.debug_module_list = kdm->next;
debug_print(srtp_mod_crypto_kernel,
"freeing memory for debug module %s", kdm->mod->name);
srtp_crypto_free(kdm);
}
/* return to insecure state */
crypto_kernel.state = srtp_crypto_kernel_state_insecure;
return srtp_err_status_ok;
}
static inline srtp_err_status_t srtp_crypto_kernel_do_load_cipher_type(
const srtp_cipher_type_t *new_ct,
srtp_cipher_type_id_t id,
int replace)
{
srtp_kernel_cipher_type_t *ctype, *new_ctype;
srtp_err_status_t status;
/* defensive coding */
if (new_ct == NULL) {
return srtp_err_status_bad_param;
}
if (new_ct->id != id) {
return srtp_err_status_bad_param;
}
/* check cipher type by running self-test */
status = srtp_cipher_type_self_test(new_ct);
if (status) {
return status;
}
/* walk down list, checking if this type is in the list already */
ctype = crypto_kernel.cipher_type_list;
while (ctype != NULL) {
if (id == ctype->id) {
if (!replace) {
return srtp_err_status_bad_param;
}
status =
srtp_cipher_type_test(new_ct, ctype->cipher_type->test_data);
if (status) {
return status;
}
new_ctype = ctype;
break;
} else if (new_ct == ctype->cipher_type) {
return srtp_err_status_bad_param;
}
ctype = ctype->next;
}
/* if not found, put new_ct at the head of the list */
if (ctype == NULL) {
/* allocate memory */
new_ctype = (srtp_kernel_cipher_type_t *)srtp_crypto_alloc(
sizeof(srtp_kernel_cipher_type_t));
if (new_ctype == NULL) {
return srtp_err_status_alloc_fail;
}
new_ctype->next = crypto_kernel.cipher_type_list;
/* set head of list to new cipher type */
crypto_kernel.cipher_type_list = new_ctype;
}
/* set fields */
new_ctype->cipher_type = new_ct;
new_ctype->id = id;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_load_cipher_type(
const srtp_cipher_type_t *new_ct,
srtp_cipher_type_id_t id)
{
return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 0);
}
srtp_err_status_t srtp_replace_cipher_type(const srtp_cipher_type_t *new_ct,
srtp_cipher_type_id_t id)
{
return srtp_crypto_kernel_do_load_cipher_type(new_ct, id, 1);
}
srtp_err_status_t srtp_crypto_kernel_do_load_auth_type(
const srtp_auth_type_t *new_at,
srtp_auth_type_id_t id,
int replace)
{
srtp_kernel_auth_type_t *atype, *new_atype;
srtp_err_status_t status;
/* defensive coding */
if (new_at == NULL) {
return srtp_err_status_bad_param;
}
if (new_at->id != id) {
return srtp_err_status_bad_param;
}
/* check auth type by running self-test */
status = srtp_auth_type_self_test(new_at);
if (status) {
return status;
}
/* walk down list, checking if this type is in the list already */
atype = crypto_kernel.auth_type_list;
while (atype != NULL) {
if (id == atype->id) {
if (!replace) {
return srtp_err_status_bad_param;
}
status = srtp_auth_type_test(new_at, atype->auth_type->test_data);
if (status) {
return status;
}
new_atype = atype;
break;
} else if (new_at == atype->auth_type) {
return srtp_err_status_bad_param;
}
atype = atype->next;
}
/* if not found, put new_at at the head of the list */
if (atype == NULL) {
/* allocate memory */
new_atype = (srtp_kernel_auth_type_t *)srtp_crypto_alloc(
sizeof(srtp_kernel_auth_type_t));
if (new_atype == NULL) {
return srtp_err_status_alloc_fail;
}
new_atype->next = crypto_kernel.auth_type_list;
/* set head of list to new auth type */
crypto_kernel.auth_type_list = new_atype;
}
/* set fields */
new_atype->auth_type = new_at;
new_atype->id = id;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_load_auth_type(
const srtp_auth_type_t *new_at,
srtp_auth_type_id_t id)
{
return srtp_crypto_kernel_do_load_auth_type(new_at, id, 0);
}
srtp_err_status_t srtp_replace_auth_type(const srtp_auth_type_t *new_at,
srtp_auth_type_id_t id)
{
return srtp_crypto_kernel_do_load_auth_type(new_at, id, 1);
}
const srtp_cipher_type_t *srtp_crypto_kernel_get_cipher_type(
srtp_cipher_type_id_t id)
{
srtp_kernel_cipher_type_t *ctype;
/* walk down list, looking for id */
ctype = crypto_kernel.cipher_type_list;
while (ctype != NULL) {
if (id == ctype->id) {
return ctype->cipher_type;
}
ctype = ctype->next;
}
/* haven't found the right one, indicate failure by returning NULL */
return NULL;
}
srtp_err_status_t srtp_crypto_kernel_alloc_cipher(srtp_cipher_type_id_t id,
srtp_cipher_pointer_t *cp,
int key_len,
int tag_len)
{
const srtp_cipher_type_t *ct;
/*
* if the crypto_kernel is not yet initialized, we refuse to allocate
* any ciphers - this is a bit extra-paranoid
*/
if (crypto_kernel.state != srtp_crypto_kernel_state_secure) {
return srtp_err_status_init_fail;
}
ct = srtp_crypto_kernel_get_cipher_type(id);
if (!ct) {
return srtp_err_status_fail;
}
return ((ct)->alloc(cp, key_len, tag_len));
}
const srtp_auth_type_t *srtp_crypto_kernel_get_auth_type(srtp_auth_type_id_t id)
{
srtp_kernel_auth_type_t *atype;
/* walk down list, looking for id */
atype = crypto_kernel.auth_type_list;
while (atype != NULL) {
if (id == atype->id) {
return atype->auth_type;
}
atype = atype->next;
}
/* haven't found the right one, indicate failure by returning NULL */
return NULL;
}
srtp_err_status_t srtp_crypto_kernel_alloc_auth(srtp_auth_type_id_t id,
srtp_auth_pointer_t *ap,
int key_len,
int tag_len)
{
const srtp_auth_type_t *at;
/*
* if the crypto_kernel is not yet initialized, we refuse to allocate
* any auth functions - this is a bit extra-paranoid
*/
if (crypto_kernel.state != srtp_crypto_kernel_state_secure) {
return srtp_err_status_init_fail;
}
at = srtp_crypto_kernel_get_auth_type(id);
if (!at) {
return srtp_err_status_fail;
}
return ((at)->alloc(ap, key_len, tag_len));
}
srtp_err_status_t srtp_crypto_kernel_load_debug_module(
srtp_debug_module_t *new_dm)
{
srtp_kernel_debug_module_t *kdm, *new;
/* defensive coding */
if (new_dm == NULL || new_dm->name == NULL) {
return srtp_err_status_bad_param;
}
/* walk down list, checking if this type is in the list already */
kdm = crypto_kernel.debug_module_list;
while (kdm != NULL) {
if (strncmp(new_dm->name, kdm->mod->name, 64) == 0) {
return srtp_err_status_bad_param;
}
kdm = kdm->next;
}
/* put new_dm at the head of the list */
/* allocate memory */
new = (srtp_kernel_debug_module_t *)srtp_crypto_alloc(
sizeof(srtp_kernel_debug_module_t));
if (new == NULL) {
return srtp_err_status_alloc_fail;
}
/* set fields */
new->mod = new_dm;
new->next = crypto_kernel.debug_module_list;
/* set head of list to new cipher type */
crypto_kernel.debug_module_list = new;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_crypto_kernel_set_debug_module(const char *name, int on)
{
srtp_kernel_debug_module_t *kdm;
/* walk down list, checking if this type is in the list already */
kdm = crypto_kernel.debug_module_list;
while (kdm != NULL) {
if (strncmp(name, kdm->mod->name, 64) == 0) {
kdm->mod->on = on;
return srtp_err_status_ok;
}
kdm = kdm->next;
}
return srtp_err_status_fail;
}

View file

@ -0,0 +1,108 @@
/*
* err.c
*
* error status reporting functions
*
* David A. McGrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright(c) 2001-2017 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "err.h"
#include "datatypes.h"
#include <string.h>
/* srtp_err_file is the FILE to which errors are reported */
static FILE *srtp_err_file = NULL;
srtp_err_status_t srtp_err_reporting_init()
{
#ifdef ERR_REPORTING_STDOUT
srtp_err_file = stdout;
#elif defined(ERR_REPORTING_FILE)
/* open file for error reporting */
srtp_err_file = fopen(ERR_REPORTING_FILE, "w");
if (srtp_err_file == NULL) {
return srtp_err_status_init_fail;
}
#endif
return srtp_err_status_ok;
}
static srtp_err_report_handler_func_t *srtp_err_report_handler = NULL;
srtp_err_status_t srtp_install_err_report_handler(
srtp_err_report_handler_func_t func)
{
srtp_err_report_handler = func;
return srtp_err_status_ok;
}
void srtp_err_report(srtp_err_reporting_level_t level, const char *format, ...)
{
char msg[512];
va_list args;
if (srtp_err_file != NULL) {
va_start(args, format);
vfprintf(srtp_err_file, format, args);
va_end(args);
}
if (srtp_err_report_handler != NULL) {
va_start(args, format);
if (vsnprintf(msg, sizeof(msg), format, args) > 0) {
/* strip trailing \n, callback should not have one */
size_t l = strlen(msg);
if (l && msg[l - 1] == '\n') {
msg[l - 1] = '\0';
}
srtp_err_report_handler(level, msg);
/*
* NOTE, need to be carefull, there is a potential that
* octet_string_set_to_zero() could
* call srtp_err_report() in the future, leading to recursion
*/
octet_string_set_to_zero(msg, sizeof(msg));
}
va_end(args);
}
}

View file

@ -0,0 +1,122 @@
/*
* key.c
*
* key usage limits enforcement
*
* David A. Mcgrew
* Cisco Systems, Inc.
*/
/*
*
* Copyright (c) 2001-2017 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.
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "key.h"
#define soft_limit 0x10000
srtp_err_status_t srtp_key_limit_set(srtp_key_limit_t key,
const srtp_xtd_seq_num_t s)
{
#ifdef NO_64BIT_MATH
if (high32(s) == 0 && low32(s) < soft_limit) {
return srtp_err_status_bad_param;
}
#else
if (s < soft_limit) {
return srtp_err_status_bad_param;
}
#endif
key->num_left = s;
key->state = srtp_key_state_normal;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_key_limit_clone(srtp_key_limit_t original,
srtp_key_limit_t *new_key)
{
if (original == NULL) {
return srtp_err_status_bad_param;
}
*new_key = original;
return srtp_err_status_ok;
}
srtp_err_status_t srtp_key_limit_check(const srtp_key_limit_t key)
{
if (key->state == srtp_key_state_expired) {
return srtp_err_status_key_expired;
}
return srtp_err_status_ok;
}
srtp_key_event_t srtp_key_limit_update(srtp_key_limit_t key)
{
#ifdef NO_64BIT_MATH
if (low32(key->num_left) == 0) {
// carry
key->num_left =
make64(high32(key->num_left) - 1, low32(key->num_left) - 1);
} else {
// no carry
key->num_left = make64(high32(key->num_left), low32(key->num_left) - 1);
}
if (high32(key->num_left) != 0 || low32(key->num_left) >= soft_limit) {
return srtp_key_event_normal; /* we're above the soft limit */
}
#else
key->num_left--;
if (key->num_left >= soft_limit) {
return srtp_key_event_normal; /* we're above the soft limit */
}
#endif
if (key->state == srtp_key_state_normal) {
/* we just passed the soft limit, so change the state */
key->state = srtp_key_state_past_soft_limit;
}
#ifdef NO_64BIT_MATH
if (low32(key->num_left) == 0 && high32(key->num_left == 0))
#else
if (key->num_left < 1)
#endif
{ /* we just hit the hard limit */
key->state = srtp_key_state_expired;
return srtp_key_event_hard_limit;
}
return srtp_key_event_soft_limit;
}