mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-26 23:15:41 +01:00
5d96a3dcde
In the ecdsa.c sample application we don't use hashing, we use ecdsa directly on a buffer containing plain text. Although the text explains that it should be the message hash it still can be confusing. Any misunderstandings here are potentially very dangerous, because ECDSA truncates the message hash if necessary and this can lead to trivial signature forgeries if the API is misused and the message is passed directly to the function without hashing. This commit adds a hash computation step to the ecdsa.c sample application and clarification to the doxygen documentation of the ECDSA functions involved.
261 lines
7.0 KiB
C
261 lines
7.0 KiB
C
/*
|
|
* Example ECDSA program
|
|
*
|
|
* Copyright (C) 2013, ARM Limited, All Rights Reserved
|
|
*
|
|
* This file is part of mbed TLS (https://tls.mbed.org)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#if !defined(POLARSSL_CONFIG_FILE)
|
|
#include "polarssl/config.h"
|
|
#else
|
|
#include POLARSSL_CONFIG_FILE
|
|
#endif
|
|
|
|
#if defined(POLARSSL_PLATFORM_C)
|
|
#include "polarssl/platform.h"
|
|
#else
|
|
#include <stdio.h>
|
|
#define polarssl_printf printf
|
|
#endif
|
|
|
|
#if defined(POLARSSL_ECDSA_C) && \
|
|
defined(POLARSSL_ENTROPY_C) && defined(POLARSSL_CTR_DRBG_C)
|
|
#include "polarssl/entropy.h"
|
|
#include "polarssl/ctr_drbg.h"
|
|
#include "polarssl/ecdsa.h"
|
|
#include "polarssl/sha256.h"
|
|
|
|
#include <string.h>
|
|
#endif
|
|
|
|
/*
|
|
* Uncomment to show key and signature details
|
|
*/
|
|
#define VERBOSE
|
|
|
|
/*
|
|
* Uncomment to force use of a specific curve
|
|
*/
|
|
#define ECPARAMS POLARSSL_ECP_DP_SECP192R1
|
|
|
|
#if !defined(ECPARAMS)
|
|
#define ECPARAMS ecp_curve_list()->grp_id
|
|
#endif
|
|
|
|
#if !defined(POLARSSL_ECDSA_C) || \
|
|
!defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C)
|
|
int main( void )
|
|
{
|
|
polarssl_printf("POLARSSL_ECDSA_C and/or "
|
|
"POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C not defined\n");
|
|
return( 0 );
|
|
}
|
|
#else
|
|
#if defined(VERBOSE)
|
|
static void dump_buf( const char *title, unsigned char *buf, size_t len )
|
|
{
|
|
size_t i;
|
|
|
|
polarssl_printf( "%s", title );
|
|
for( i = 0; i < len; i++ )
|
|
polarssl_printf("%c%c", "0123456789ABCDEF" [buf[i] / 16],
|
|
"0123456789ABCDEF" [buf[i] % 16] );
|
|
polarssl_printf( "\n" );
|
|
}
|
|
|
|
static void dump_pubkey( const char *title, ecdsa_context *key )
|
|
{
|
|
unsigned char buf[300];
|
|
size_t len;
|
|
|
|
if( ecp_point_write_binary( &key->grp, &key->Q,
|
|
POLARSSL_ECP_PF_UNCOMPRESSED, &len, buf, sizeof buf ) != 0 )
|
|
{
|
|
polarssl_printf("internal error\n");
|
|
return;
|
|
}
|
|
|
|
dump_buf( title, buf, len );
|
|
}
|
|
#else
|
|
#define dump_buf( a, b, c )
|
|
#define dump_pubkey( a, b )
|
|
#endif
|
|
|
|
int main( int argc, char *argv[] )
|
|
{
|
|
int ret;
|
|
ecdsa_context ctx_sign, ctx_verify;
|
|
entropy_context entropy;
|
|
ctr_drbg_context ctr_drbg;
|
|
sha256_context sha256_ctx;
|
|
unsigned char message[100];
|
|
unsigned char hash[32];
|
|
unsigned char sig[POLARSSL_ECDSA_MAX_LEN];
|
|
size_t sig_len;
|
|
const char *pers = "ecdsa";
|
|
((void) argv);
|
|
|
|
ecdsa_init( &ctx_sign );
|
|
ecdsa_init( &ctx_verify );
|
|
sha256_init( &sha256_ctx );
|
|
|
|
memset( sig, 0, sizeof( sig ) );
|
|
memset( message, 0x25, sizeof( message ) );
|
|
ret = 1;
|
|
|
|
if( argc != 1 )
|
|
{
|
|
polarssl_printf( "usage: ecdsa\n" );
|
|
|
|
#if defined(_WIN32)
|
|
polarssl_printf( "\n" );
|
|
#endif
|
|
|
|
goto exit;
|
|
}
|
|
|
|
/*
|
|
* Generate a key pair for signing
|
|
*/
|
|
polarssl_printf( "\n . Seeding the random number generator..." );
|
|
fflush( stdout );
|
|
|
|
entropy_init( &entropy );
|
|
if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
|
|
(const unsigned char *) pers,
|
|
strlen( pers ) ) ) != 0 )
|
|
{
|
|
polarssl_printf( " failed\n ! ctr_drbg_init returned %d\n", ret );
|
|
goto exit;
|
|
}
|
|
|
|
polarssl_printf( " ok\n . Generating key pair..." );
|
|
fflush( stdout );
|
|
|
|
if( ( ret = ecdsa_genkey( &ctx_sign, ECPARAMS,
|
|
ctr_drbg_random, &ctr_drbg ) ) != 0 )
|
|
{
|
|
polarssl_printf( " failed\n ! ecdsa_genkey returned %d\n", ret );
|
|
goto exit;
|
|
}
|
|
|
|
polarssl_printf( " ok (key size: %d bits)\n", (int) ctx_sign.grp.pbits );
|
|
|
|
dump_pubkey( " + Public key: ", &ctx_sign );
|
|
|
|
/*
|
|
* Compute message hash
|
|
*/
|
|
polarssl_printf( " . Signing message..." );
|
|
polarssl_printf( " . Computing message hash..." );
|
|
fflush( stdout );
|
|
|
|
sha256_starts( &sha256_ctx, 0 );
|
|
sha256_update( &sha256_ctx, message, sizeof( message ) );
|
|
sha256_finish( &sha256_ctx, hash );
|
|
|
|
polarssl_printf( " ok\n" );
|
|
|
|
dump_buf( " + Hash: ", hash, sizeof( hash ) );
|
|
|
|
/*
|
|
* Sign message hash
|
|
*/
|
|
polarssl_printf( " . Signing message hash..." );
|
|
fflush( stdout );
|
|
|
|
if( ( ret = ecdsa_write_signature( &ctx_sign,
|
|
hash, sizeof( hash ),
|
|
sig, &sig_len,
|
|
ctr_drbg_random, &ctr_drbg ) ) != 0 )
|
|
{
|
|
polarssl_printf( " failed\n ! ecdsa_genkey returned %d\n", ret );
|
|
goto exit;
|
|
}
|
|
polarssl_printf( " ok (signature length = %u)\n", (unsigned int) sig_len );
|
|
|
|
dump_buf( " + Signature: ", sig, sig_len );
|
|
|
|
/*
|
|
* Signature is serialized as defined by RFC 4492 p. 20,
|
|
* but one can also access 'r' and 's' directly from the context
|
|
*/
|
|
#ifdef POLARSSL_FS_IO
|
|
mpi_write_file( " r = ", &ctx_sign.r, 16, NULL );
|
|
mpi_write_file( " s = ", &ctx_sign.s, 16, NULL );
|
|
#endif
|
|
|
|
/*
|
|
* Transfer public information to verifying context
|
|
*
|
|
* We could use the same context for verification and signatures, but we
|
|
* chose to use a new one in order to make it clear that the verifying
|
|
* context only needs the public key (Q), and not the private key (d).
|
|
*/
|
|
polarssl_printf( " . Preparing verification context..." );
|
|
fflush( stdout );
|
|
|
|
if( ( ret = ecp_group_copy( &ctx_verify.grp, &ctx_sign.grp ) ) != 0 )
|
|
{
|
|
polarssl_printf( " failed\n ! ecp_group_copy returned %d\n", ret );
|
|
goto exit;
|
|
}
|
|
|
|
if( ( ret = ecp_copy( &ctx_verify.Q, &ctx_sign.Q ) ) != 0 )
|
|
{
|
|
polarssl_printf( " failed\n ! ecp_copy returned %d\n", ret );
|
|
goto exit;
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
/*
|
|
* Verify signature
|
|
*/
|
|
polarssl_printf( " ok\n . Verifying signature..." );
|
|
fflush( stdout );
|
|
|
|
if( ( ret = ecdsa_read_signature( &ctx_verify,
|
|
hash, sizeof( hash ),
|
|
sig, sig_len ) ) != 0 )
|
|
{
|
|
polarssl_printf( " failed\n ! ecdsa_read_signature returned %d\n", ret );
|
|
goto exit;
|
|
}
|
|
|
|
polarssl_printf( " ok\n" );
|
|
|
|
exit:
|
|
|
|
#if defined(_WIN32)
|
|
polarssl_printf( " + Press Enter to exit this program.\n" );
|
|
fflush( stdout ); getchar();
|
|
#endif
|
|
|
|
ecdsa_free( &ctx_verify );
|
|
ecdsa_free( &ctx_sign );
|
|
ctr_drbg_free( &ctr_drbg );
|
|
entropy_free( &entropy );
|
|
sha256_free( &sha256_ctx );
|
|
|
|
return( ret );
|
|
}
|
|
#endif /* POLARSSL_ECDSA_C && POLARSSL_ENTROPY_C && POLARSSL_CTR_DRBG_C &&
|
|
ECPARAMS */
|