Files
2024-09-28 14:24:04 +08:00

294 lines
8.7 KiB
C

/**
* Copyright (C) 2015-2016 Virgil Security Inc.
*
* Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* (1) Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* (2) 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.
*
* (3) Neither the name of the copyright holder 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 AUTHOR ''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 AUTHOR 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.
*
* This file is part of extension to mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_FAST_EC_C)
#include "mbedtls/fast_ec.h"
#include "mbedtls/fast_ec_internal.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#include <string.h>
const mbedtls_fast_ec_info_t* mbedtls_fast_ec_info_from_type( mbedtls_fast_ec_type_t type )
{
switch( type )
{
case MBEDTLS_FAST_EC_X25519:
return( &mbedtls_fast_ec_x25519_info );
case MBEDTLS_FAST_EC_ED25519:
return( &mbedtls_fast_ec_ed25519_info );
default:
return( NULL );
}
}
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0;
}
void mbedtls_fast_ec_init( mbedtls_fast_ec_keypair_t *keypair )
{
memset( keypair, 0, sizeof( mbedtls_fast_ec_keypair_t ) );
}
int mbedtls_fast_ec_setup(mbedtls_fast_ec_keypair_t *keypair, const mbedtls_fast_ec_info_t* info )
{
if( info == NULL || keypair == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
keypair->public_key = mbedtls_calloc( 1, info->key_len );
keypair->private_key = mbedtls_calloc( 1, info->key_len );
if( keypair->public_key == NULL )
return( MBEDTLS_ERR_FAST_EC_ALLOC_FAILED );
if( keypair->private_key == NULL )
{
if( keypair->public_key != NULL )
{
mbedtls_free( keypair->public_key );
keypair->public_key = NULL;
}
return( MBEDTLS_ERR_FAST_EC_ALLOC_FAILED );
}
keypair->info = info;
return( 0 );
}
void mbedtls_fast_ec_free( mbedtls_fast_ec_keypair_t *keypair )
{
if( keypair == NULL )
return;
if( keypair->public_key != NULL )
{
mbedtls_zeroize( keypair->public_key, keypair->info->key_len );
mbedtls_free( keypair->public_key );
}
if( keypair->private_key != NULL )
{
mbedtls_zeroize( keypair->private_key, keypair->info->key_len );
mbedtls_free( keypair->private_key );
}
memset( keypair, 0, sizeof( mbedtls_fast_ec_keypair_t ) );
}
int mbedtls_fast_ec_copy(mbedtls_fast_ec_keypair_t* dst, const mbedtls_fast_ec_keypair_t* src)
{
int ret = 0;
if( src == NULL || src->info == NULL || dst->info != NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( ( ret = mbedtls_fast_ec_setup( dst, src->info ) ) != 0 )
return( ret );
memcpy( dst->public_key, src->public_key, src->info->key_len );
memcpy( dst->private_key, src->private_key, src->info->key_len );
return( 0 );
}
int mbedtls_fast_ec_gen_key( mbedtls_fast_ec_keypair_t *keypair,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
if( keypair == NULL || keypair->info == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
return keypair->info->gen_key_func( keypair->public_key, keypair->private_key, f_rng, p_rng );
}
int mbedtls_fast_ec_compute_pub( mbedtls_fast_ec_keypair_t *keypair )
{
if( keypair == NULL || keypair->info == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
return( keypair->info->get_pub_func( keypair->public_key, keypair->private_key ) );
}
int mbedtls_fast_ec_sign( const mbedtls_fast_ec_keypair_t* keypair,
unsigned char* sig, size_t *sig_len,
const unsigned char* data, size_t data_len )
{
int ret = 0;
if( keypair == NULL || keypair->info == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( keypair->info->sign_func == NULL )
return( MBEDTLS_ERR_FAST_EC_FEATURE_UNAVAILABLE );
if ( ( ret = keypair->info->sign_func( sig, keypair->private_key, data, data_len ) ) != 0 )
return( ret );
*sig_len = keypair->info->sig_len;
return( 0 );
}
int mbedtls_fast_ec_verify( const mbedtls_fast_ec_keypair_t* keypair,
const unsigned char* sig, size_t sig_len,
const unsigned char* data, size_t data_len)
{
if( keypair == NULL || keypair->info == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( keypair->info->verify_func == NULL )
return( MBEDTLS_ERR_FAST_EC_FEATURE_UNAVAILABLE );
if( sig_len != keypair->info->sig_len )
return( MBEDTLS_ERR_FAST_EC_SIG_LEN_MISMATCH );
if ( keypair->info->verify_func( sig, keypair->public_key, data, data_len ) != 0 )
return( MBEDTLS_ERR_FAST_EC_VERIFY_FAILED );
return( 0 );
}
int mbedtls_fast_ec_compute_shared( const mbedtls_fast_ec_keypair_t* pub, const mbedtls_fast_ec_keypair_t* prv,
unsigned char* shared, size_t shared_len )
{
if( pub == NULL || pub->info == NULL || pub->public_key == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( prv == NULL || prv->info == NULL || prv->private_key == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( pub->info->type != prv->info->type )
return( MBEDTLS_ERR_FAST_EC_PUB_PRV_MISMATCH );
return( pub->info->compute_shared_func( pub->public_key, prv->private_key, shared, shared_len ) );
}
int mbedtls_fast_ec_check_pub_priv( const mbedtls_fast_ec_keypair_t *pub, const mbedtls_fast_ec_keypair_t *prv )
{
int ret = 0;
unsigned char *public_key = NULL;
if( pub == NULL || pub->info == NULL || pub->public_key == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( prv == NULL || prv->info == NULL || prv->private_key == NULL )
return( MBEDTLS_ERR_FAST_EC_BAD_INPUT_DATA );
if( pub->info->type != prv->info->type )
return( MBEDTLS_ERR_FAST_EC_PUB_PRV_MISMATCH );
if( ( public_key = mbedtls_calloc( 1, prv->info->key_len ) ) == NULL )
return( MBEDTLS_ERR_FAST_EC_ALLOC_FAILED );
if( ( ret = prv->info->get_pub_func( public_key, prv->private_key ) ) != 0 )
goto cleanup;
if( memcmp( pub->public_key, public_key, pub->info->key_len ) != 0 )
{
ret = MBEDTLS_ERR_FAST_EC_PUB_PRV_MISMATCH;
goto cleanup;
}
cleanup:
mbedtls_free( public_key );
return( ret );
}
mbedtls_fast_ec_type_t mbedtls_fast_ec_get_type( const mbedtls_fast_ec_info_t* info )
{
if( info == NULL )
return( MBEDTLS_FAST_EC_NONE );
return( info->type );
}
const char* mbedtls_fast_ec_get_name( const mbedtls_fast_ec_info_t* info )
{
if( info == NULL )
return( NULL);
return( info->name );
}
size_t mbedtls_fast_ec_get_key_bitlen( const mbedtls_fast_ec_info_t* info )
{
if( info == NULL )
return( 0 );
return( info->key_bitlen );
}
size_t mbedtls_fast_ec_get_key_len( const mbedtls_fast_ec_info_t* info )
{
if( info == NULL )
return( 0 );
return( info->key_len );
}
size_t mbedtls_fast_ec_get_sig_len( const mbedtls_fast_ec_info_t* info )
{
if( info == NULL )
return( 0 );
return( info->sig_len );
}
size_t mbedtls_fast_ec_get_shared_len( const mbedtls_fast_ec_info_t* info )
{
if( info == NULL )
return( 0 );
return( info->dh_len );
}
#endif /* MBEDTLS_FAST_EC_C */