409 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			409 lines
		
	
	
		
			11 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_ECIES_C)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_ECP_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/ecp.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_FAST_EC_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/fast_ec.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_ECDH_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/ecdh.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_MD_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/md.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_PK_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/pk.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_KDF_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/kdf.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_CIPHER_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/cipher.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_ASN1_PARSE_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/asn1.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_ASN1_WRITE_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/asn1write.h"
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_PLATFORM_C)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/platform.h"
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#define mbedtls_calloc    calloc
							 | 
						||
| 
								 | 
							
								#define mbedtls_free      free
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "mbedtls/ecies_internal.h"
							 | 
						||
| 
								 | 
							
								#include "mbedtls/ecies_envelope.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define ECIES_OCTET_SIZE 8
							 | 
						||
| 
								 | 
							
								#define ECIES_SIZE_TO_OCTETS(size) ((size + 7) / ECIES_OCTET_SIZE)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define INVOKE_AND_CHECK(result,invocation) \
							 | 
						||
| 
								 | 
							
								    if ((result = invocation) < 0) goto cleanup;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define ACCUMULATE_AND_CHECK(result, len, invocation) \
							 | 
						||
| 
								 | 
							
								do { \
							 | 
						||
| 
								 | 
							
								    if ((result = invocation) < 0) { \
							 | 
						||
| 
								 | 
							
								        goto cleanup; \
							 | 
						||
| 
								 | 
							
								    } else { \
							 | 
						||
| 
								 | 
							
								        len += result; \
							 | 
						||
| 
								 | 
							
								        result = 0; \
							 | 
						||
| 
								 | 
							
								    } \
							 | 
						||
| 
								 | 
							
								} while (0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int asn1_get_tag_len(unsigned char *p, const unsigned char *end,
							 | 
						||
| 
								 | 
							
								        size_t *len)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    unsigned char *len_p = p + 1;
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_asn1_get_len(&len_p, end, len)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    *len += len_p - p;
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const mbedtls_ecies_info_t* mbedtls_ecies_info_from_type(mbedtls_ecies_type_t type)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    switch( type )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_ECP_C) && defined (MBEDTLS_ECDH_C)
							 | 
						||
| 
								 | 
							
								        case MBEDTLS_ECIES_ECP:
							 | 
						||
| 
								 | 
							
								            return( &mbedtls_ecies_ecp_info );
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_FAST_EC_C)
							 | 
						||
| 
								 | 
							
								        case MBEDTLS_ECIES_FAST_EC:
							 | 
						||
| 
								 | 
							
								            return( &mbedtls_ecies_fast_ec_info );
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								            return( NULL );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_ECP_C) && defined (MBEDTLS_ECDH_C)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void * ecp_key_alloc_wrap( void )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* key = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( key != NULL ) {
							 | 
						||
| 
								 | 
							
								        mbedtls_ecp_keypair_init( key );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return key;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void ecp_key_free_wrap( void *key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) key );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int ecp_key_gen_ephemeral_wrap( void *src_key, void *dst_key,
							 | 
						||
| 
								 | 
							
								        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* src = (mbedtls_ecp_keypair *) src_key;
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* dst = (mbedtls_ecp_keypair *) dst_key;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return( mbedtls_ecp_gen_key( src->grp.id, dst, f_rng, p_rng ) );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int ecp_key_compute_shared_wrap( void *pub, void* prv,
							 | 
						||
| 
								 | 
							
								        unsigned char* shared, size_t shared_len,
							 | 
						||
| 
								 | 
							
								        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    mbedtls_mpi shared_mpi;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* public = (mbedtls_ecp_keypair *) pub;
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* private = (mbedtls_ecp_keypair *) prv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (public->grp.id != private->grp.id)
							 | 
						||
| 
								 | 
							
								        return MBEDTLS_ERR_ECIES_BAD_INPUT_DATA;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_mpi_init( &shared_mpi );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_ecdh_compute_shared( &public->grp, &shared_mpi, &public->Q, &private->d,
							 | 
						||
| 
								 | 
							
								                                         f_rng, p_rng )
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_mpi_write_binary(&shared_mpi, shared, shared_len)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    mbedtls_mpi_free( &shared_mpi );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return( result );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static size_t ecp_key_get_shared_len_wrap( void* key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* ecp_key = (mbedtls_ecp_keypair *) key;
							 | 
						||
| 
								 | 
							
								    return( ECIES_SIZE_TO_OCTETS( ecp_key->grp.pbits ) );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int ecp_key_write_pub_asn1_wrap( unsigned char** p, unsigned char* start, void *key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    size_t len = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_context pk;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pk.pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
							 | 
						||
| 
								 | 
							
								    pk.pk_ctx = key;
							 | 
						||
| 
								 | 
							
								    ACCUMULATE_AND_CHECK(result, len,
							 | 
						||
| 
								 | 
							
								        mbedtls_pk_write_pubkey_der(&pk, start , *p - start)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    *p -= len;
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    if (result < 0)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								        return (int)len;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int ecp_key_read_pub_asn1_wrap( unsigned char** p, const unsigned char* end, void *key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_context pk;
							 | 
						||
| 
								 | 
							
								    size_t key_len = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_ecp_keypair* ecp_key = (mbedtls_ecp_keypair *) key;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_init(&pk);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        asn1_get_tag_len(*p, end, &key_len)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_pk_parse_public_key(&pk, *p, key_len)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    *p += key_len;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mbedtls_pk_can_do(&pk, MBEDTLS_PK_ECKEY) ||
							 | 
						||
| 
								 | 
							
								        mbedtls_pk_can_do(&pk, MBEDTLS_PK_ECKEY_DH) ||
							 | 
						||
| 
								 | 
							
								        mbedtls_pk_can_do(&pk, MBEDTLS_PK_ECDSA))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								            mbedtls_ecp_group_copy( &ecp_key->grp, &mbedtls_pk_ec(pk)->grp )
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								            mbedtls_mpi_copy( &ecp_key->d, &mbedtls_pk_ec(pk)->d )
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								            mbedtls_ecp_copy( &ecp_key->Q, &mbedtls_pk_ec(pk)->Q )
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        result = MBEDTLS_ERR_ECIES_MALFORMED_DATA;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_free(&pk);
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const mbedtls_ecies_info_t mbedtls_ecies_ecp_info = {
							 | 
						||
| 
								 | 
							
								    MBEDTLS_ECIES_ECP, // type
							 | 
						||
| 
								 | 
							
								    "ECIES_ECP", // name
							 | 
						||
| 
								 | 
							
								    ecp_key_alloc_wrap, // key_alloc_func
							 | 
						||
| 
								 | 
							
								    ecp_key_free_wrap, // key_free_func
							 | 
						||
| 
								 | 
							
								    ecp_key_gen_ephemeral_wrap, // key_gen_ephemeral_func
							 | 
						||
| 
								 | 
							
								    ecp_key_compute_shared_wrap, // key_make_shared_func
							 | 
						||
| 
								 | 
							
								    ecp_key_get_shared_len_wrap, // key_get_shared_len_func
							 | 
						||
| 
								 | 
							
								    ecp_key_write_pub_asn1_wrap, // key_write_pub_asn1_func
							 | 
						||
| 
								 | 
							
								    ecp_key_read_pub_asn1_wrap, // key_read_pub_asn1_func
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* MBEDTLS_ECP_C &&  MBEDTLS_ECDH_C */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_FAST_EC_C)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void * fast_ec_key_alloc_wrap( void )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_keypair_t* key = mbedtls_calloc( 1, sizeof( mbedtls_fast_ec_keypair_t ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( key != NULL ) {
							 | 
						||
| 
								 | 
							
								        mbedtls_fast_ec_init( key );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return key;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void fast_ec_key_free_wrap( void *key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_free( (mbedtls_fast_ec_keypair_t *) key );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fast_ec_key_gen_ephemeral_wrap( void *src_key, void *dst_key,
							 | 
						||
| 
								 | 
							
								        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_keypair_t* src = (mbedtls_fast_ec_keypair_t *) src_key;
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_keypair_t* dst = (mbedtls_fast_ec_keypair_t *) dst_key;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_fast_ec_setup( dst, src->info )
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_fast_ec_gen_key( dst, f_rng, p_rng )
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    return( result );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fast_ec_key_compute_shared_wrap( void *pub, void* prv,
							 | 
						||
| 
								 | 
							
								        unsigned char* shared, size_t shared_len,
							 | 
						||
| 
								 | 
							
								        int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_keypair_t* public = (mbedtls_fast_ec_keypair_t *) pub;
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_keypair_t* private = (mbedtls_fast_ec_keypair_t *) prv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    (void) f_rng;
							 | 
						||
| 
								 | 
							
								    (void) p_rng;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( mbedtls_fast_ec_get_type( public->info ) != mbedtls_fast_ec_get_type( private->info ) )
							 | 
						||
| 
								 | 
							
								        return MBEDTLS_ERR_ECIES_BAD_INPUT_DATA;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return( mbedtls_fast_ec_compute_shared( public, private, shared, shared_len ) );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static size_t fast_ec_key_get_shared_len_wrap( void* key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    return( mbedtls_fast_ec_get_shared_len( ( (mbedtls_fast_ec_keypair_t *) key )->info ) );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fast_ec_key_write_pub_asn1_wrap( unsigned char** p, unsigned char* start, void *key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    size_t len = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_context pk;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pk.pk_info = mbedtls_pk_info_from_type( mbedtls_pk_from_fast_ec_type(
							 | 
						||
| 
								 | 
							
								            mbedtls_fast_ec_get_type( ( (mbedtls_fast_ec_keypair_t *) key )->info ) ) );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if( pk.pk_info == NULL)
							 | 
						||
| 
								 | 
							
								        INVOKE_AND_CHECK( result, MBEDTLS_ERR_ECIES_MALFORMED_DATA );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    pk.pk_ctx = key;
							 | 
						||
| 
								 | 
							
								    ACCUMULATE_AND_CHECK(result, len,
							 | 
						||
| 
								 | 
							
								        mbedtls_pk_write_pubkey_der(&pk, start , *p - start)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    *p -= len;
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    if (result < 0)
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								        return (int)len;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int fast_ec_key_read_pub_asn1_wrap( unsigned char** p, const unsigned char* end, void *key )
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_context pk;
							 | 
						||
| 
								 | 
							
								    size_t key_len = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_fast_ec_keypair_t* fast_ec_key = (mbedtls_fast_ec_keypair_t *) key;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_init(&pk);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        asn1_get_tag_len(*p, end, &key_len)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								        mbedtls_pk_parse_public_key(&pk, *p, key_len)
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								    *p += key_len;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (mbedtls_pk_can_do(&pk, MBEDTLS_PK_X25519) || mbedtls_pk_can_do(&pk, MBEDTLS_PK_ED25519) )
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        INVOKE_AND_CHECK(result,
							 | 
						||
| 
								 | 
							
								            mbedtls_fast_ec_copy( fast_ec_key, mbedtls_pk_fast_ec(pk) )
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        result = MBEDTLS_ERR_ECIES_MALFORMED_DATA;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								cleanup:
							 | 
						||
| 
								 | 
							
								    mbedtls_pk_free(&pk);
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const mbedtls_ecies_info_t mbedtls_ecies_fast_ec_info = {
							 | 
						||
| 
								 | 
							
								    MBEDTLS_ECIES_FAST_EC, // type
							 | 
						||
| 
								 | 
							
								    "ECIES_FAST_EC", // name
							 | 
						||
| 
								 | 
							
								    fast_ec_key_alloc_wrap, // key_alloc_func
							 | 
						||
| 
								 | 
							
								    fast_ec_key_free_wrap, // key_free_func
							 | 
						||
| 
								 | 
							
								    fast_ec_key_gen_ephemeral_wrap, // key_gen_ephemeral_func
							 | 
						||
| 
								 | 
							
								    fast_ec_key_compute_shared_wrap, // key_make_shared_func
							 | 
						||
| 
								 | 
							
								    fast_ec_key_get_shared_len_wrap, // key_get_shared_len_func
							 | 
						||
| 
								 | 
							
								    fast_ec_key_write_pub_asn1_wrap, // key_write_pub_asn1_func
							 | 
						||
| 
								 | 
							
								    fast_ec_key_read_pub_asn1_wrap, // key_read_pub_asn1_func
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* MBEDTLS_FAST_EC_C */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* MBEDTLS_ECIES_C */
							 |