294 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			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 */
 |