Files
kunlun/rom/riscv3/romlib/crypto/mbedtls-2.4.0/library/ecies_wrap.c
2024-09-28 14:24:04 +08:00

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 */