Return and propagate UECC_FAULT_DETECTED
This commit first changes the return convention of EccPoint_mult_safer() so that it properly reports when faults are detected. Then all functions that call it need to be changed to (1) follow the same return convention and (2) properly propagate UECC_FAULT_DETECTED when it occurs. Here's the reverse call graph from EccPoint_mult_safer() to the rest of the library (where return values are translated to the MBEDTLS_ERR_ space) and test functions (where expected return values are asserted explicitly). EccPoint_mult_safer() EccPoint_compute_public_key() uECC_compute_public_key() pkparse.c tests/suites/test_suite_pkparse.function uECC_make_key_with_d() uECC_make_key() ssl_cli.c ssl_srv.c tests/suites/test_suite_pk.function tests/suites/test_suite_tinycrypt.function uECC_shared_secret() ssl_tls.c tests/suites/test_suite_tinycrypt.function uECC_sign_with_k() uECC_sign() pk.c tests/suites/test_suite_tinycrypt.function Note: in uECC_sign_with_k() a test for uECC_vli_isZero(p) is suppressed because it is redundant with a more thorough test (point validity) done at the end of EccPoint_mult_safer(). This redundancy was introduced in a previous commit but not noticed earlier.
This commit is contained in:
parent
4d6186beb0
commit
9d6a535ba1
14 changed files with 112 additions and 96 deletions
|
@ -217,7 +217,7 @@ int uECC_curve_public_key_size(void);
|
||||||
* @param private_key IN -- The private key to compute the public key for
|
* @param private_key IN -- The private key to compute the public key for
|
||||||
* @param public_key OUT -- Will be filled in with the corresponding public key
|
* @param public_key OUT -- Will be filled in with the corresponding public key
|
||||||
* @param curve
|
* @param curve
|
||||||
* @return Returns 1 if key was computed successfully, 0 if an error occurred.
|
* @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED
|
||||||
*/
|
*/
|
||||||
int uECC_compute_public_key(const uint8_t *private_key,
|
int uECC_compute_public_key(const uint8_t *private_key,
|
||||||
uint8_t *public_key);
|
uint8_t *public_key);
|
||||||
|
@ -228,6 +228,7 @@ int uECC_compute_public_key(const uint8_t *private_key,
|
||||||
* @param result OUT -- public-key
|
* @param result OUT -- public-key
|
||||||
* @param private_key IN -- private-key
|
* @param private_key IN -- private-key
|
||||||
* @param curve IN -- elliptic curve
|
* @param curve IN -- elliptic curve
|
||||||
|
* @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED
|
||||||
*/
|
*/
|
||||||
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||||
uECC_word_t *private_key);
|
uECC_word_t *private_key);
|
||||||
|
@ -241,6 +242,7 @@ uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||||
* @param result OUT -- returns scalar*point
|
* @param result OUT -- returns scalar*point
|
||||||
* @param point IN -- elliptic curve point
|
* @param point IN -- elliptic curve point
|
||||||
* @param scalar IN -- scalar
|
* @param scalar IN -- scalar
|
||||||
|
* @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED
|
||||||
*/
|
*/
|
||||||
int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||||
const uECC_word_t * scalar);
|
const uECC_word_t * scalar);
|
||||||
|
|
|
@ -83,8 +83,7 @@ extern "C" {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a public/private key pair.
|
* @brief Create a public/private key pair.
|
||||||
* @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
|
* @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED
|
||||||
* returns TC_CRYPTO_FAIL (0) if error while generating key pair
|
|
||||||
*
|
*
|
||||||
* @param p_public_key OUT -- Will be filled in with the public key. Must be at
|
* @param p_public_key OUT -- Will be filled in with the public key. Must be at
|
||||||
* least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
|
* least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
|
||||||
|
@ -114,8 +113,7 @@ int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
|
||||||
/**
|
/**
|
||||||
* @brief Compute a shared secret given your secret key and someone else's
|
* @brief Compute a shared secret given your secret key and someone else's
|
||||||
* public key.
|
* public key.
|
||||||
* @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
|
* @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED
|
||||||
* returns TC_CRYPTO_FAIL (0) otherwise
|
|
||||||
*
|
*
|
||||||
* @param p_secret OUT -- Will be filled in with the shared secret value. Must be
|
* @param p_secret OUT -- Will be filled in with the shared secret value. Must be
|
||||||
* the same size as the curve size (for curve secp256r1, secret must be 32 bytes
|
* the same size as the curve size (for curve secp256r1, secret must be 32 bytes
|
||||||
|
|
|
@ -92,8 +92,7 @@ extern "C" {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate an ECDSA signature for a given hash value.
|
* @brief Generate an ECDSA signature for a given hash value.
|
||||||
* @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
|
* @return UECC_SUCCESS or UECC_FAILURE or UECC_FAULT_DETECTED
|
||||||
* returns TC_CRYPTO_FAIL (0) if an error occurred.
|
|
||||||
*
|
*
|
||||||
* @param p_private_key IN -- Your private key.
|
* @param p_private_key IN -- Your private key.
|
||||||
* @param p_message_hash IN -- The hash of the message to sign.
|
* @param p_message_hash IN -- The hash of the message to sign.
|
||||||
|
|
|
@ -723,8 +723,9 @@ static int uecc_eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
|
||||||
#define MAX_SECP256R1_ECDSA_SIG_LEN ( 3 + 2 * ( 3 + NUM_ECC_BYTES ) )
|
#define MAX_SECP256R1_ECDSA_SIG_LEN ( 3 + 2 * ( 3 + NUM_ECC_BYTES ) )
|
||||||
|
|
||||||
ret = uECC_sign( keypair->private_key, hash, hash_len, sig );
|
ret = uECC_sign( keypair->private_key, hash, hash_len, sig );
|
||||||
/* TinyCrypt uses 0 to signal errors. */
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
if( ret == 0 )
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
|
if( ret != UECC_SUCCESS )
|
||||||
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
|
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
|
||||||
|
|
||||||
*sig_len = 2 * NUM_ECC_BYTES;
|
*sig_len = 2 * NUM_ECC_BYTES;
|
||||||
|
|
|
@ -987,7 +987,9 @@ static int pk_parse_key_sec1_der( mbedtls_uecc_keypair *keypair,
|
||||||
{
|
{
|
||||||
ret = uECC_compute_public_key( keypair->private_key,
|
ret = uECC_compute_public_key( keypair->private_key,
|
||||||
keypair->public_key );
|
keypair->public_key );
|
||||||
if( ret == 0 )
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
|
if( ret != UECC_SUCCESS )
|
||||||
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
|
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3568,7 +3568,6 @@ static int ssl_out_client_key_exchange_write( mbedtls_ssl_context *ssl,
|
||||||
|
|
||||||
{
|
{
|
||||||
((void) n);
|
((void) n);
|
||||||
((void) ret);
|
|
||||||
|
|
||||||
if( (size_t)( end - p ) < 2 * NUM_ECC_BYTES + 2 )
|
if( (size_t)( end - p ) < 2 * NUM_ECC_BYTES + 2 )
|
||||||
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||||
|
@ -3576,10 +3575,11 @@ static int ssl_out_client_key_exchange_write( mbedtls_ssl_context *ssl,
|
||||||
*p++ = 2 * NUM_ECC_BYTES + 1;
|
*p++ = 2 * NUM_ECC_BYTES + 1;
|
||||||
*p++ = 0x04; /* uncompressed point presentation */
|
*p++ = 0x04; /* uncompressed point presentation */
|
||||||
|
|
||||||
if( !uECC_make_key( p, ssl->handshake->ecdh_privkey ) )
|
ret = uECC_make_key( p, ssl->handshake->ecdh_privkey );
|
||||||
{
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
|
if( ret != UECC_SUCCESS )
|
||||||
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
||||||
}
|
|
||||||
p += 2 * NUM_ECC_BYTES;
|
p += 2 * NUM_ECC_BYTES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3717,7 +3717,6 @@ static int ssl_out_client_key_exchange_write( mbedtls_ssl_context *ssl,
|
||||||
{
|
{
|
||||||
#if defined(MBEDTLS_USE_TINYCRYPT)
|
#if defined(MBEDTLS_USE_TINYCRYPT)
|
||||||
((void) n);
|
((void) n);
|
||||||
((void) ret);
|
|
||||||
|
|
||||||
if( (size_t)( end - p ) < 2 * NUM_ECC_BYTES + 2 )
|
if( (size_t)( end - p ) < 2 * NUM_ECC_BYTES + 2 )
|
||||||
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||||
|
@ -3725,10 +3724,11 @@ static int ssl_out_client_key_exchange_write( mbedtls_ssl_context *ssl,
|
||||||
*p++ = 2 * NUM_ECC_BYTES + 1;
|
*p++ = 2 * NUM_ECC_BYTES + 1;
|
||||||
*p++ = 0x04; /* uncompressed point presentation */
|
*p++ = 0x04; /* uncompressed point presentation */
|
||||||
|
|
||||||
if( !uECC_make_key( p, ssl->handshake->ecdh_privkey ) )
|
ret = uECC_make_key( p, ssl->handshake->ecdh_privkey );
|
||||||
{
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
|
if( ret != UECC_SUCCESS )
|
||||||
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
||||||
}
|
|
||||||
p += 2 * NUM_ECC_BYTES;
|
p += 2 * NUM_ECC_BYTES;
|
||||||
#else /* MBEDTLS_USE_TINYCRYPT */
|
#else /* MBEDTLS_USE_TINYCRYPT */
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -3410,6 +3410,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
|
||||||
|
|
||||||
#if defined(MBEDTLS_USE_TINYCRYPT)
|
#if defined(MBEDTLS_USE_TINYCRYPT)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
static const unsigned char ecdh_param_hdr[] = {
|
static const unsigned char ecdh_param_hdr[] = {
|
||||||
MBEDTLS_SSL_EC_TLS_NAMED_CURVE,
|
MBEDTLS_SSL_EC_TLS_NAMED_CURVE,
|
||||||
0 /* high bits of secp256r1 TLS ID */,
|
0 /* high bits of secp256r1 TLS ID */,
|
||||||
|
@ -3426,12 +3427,12 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
|
||||||
ecdh_param_hdr, sizeof( ecdh_param_hdr ) );
|
ecdh_param_hdr, sizeof( ecdh_param_hdr ) );
|
||||||
ssl->out_msglen += sizeof( ecdh_param_hdr );
|
ssl->out_msglen += sizeof( ecdh_param_hdr );
|
||||||
|
|
||||||
if( !uECC_make_key( &ssl->out_msg[ ssl->out_msglen ],
|
ret = uECC_make_key( &ssl->out_msg[ ssl->out_msglen ],
|
||||||
ssl->handshake->ecdh_privkey ) )
|
ssl->handshake->ecdh_privkey );
|
||||||
{
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "Key creation failed" ) );
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
if( ret != UECC_SUCCESS )
|
||||||
}
|
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
||||||
|
|
||||||
ssl->out_msglen += 2*NUM_ECC_BYTES;
|
ssl->out_msglen += 2*NUM_ECC_BYTES;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1973,14 +1973,13 @@ int mbedtls_ssl_build_pms( mbedtls_ssl_context *ssl )
|
||||||
mbedtls_ssl_suite_get_key_exchange( ciphersuite_info )
|
mbedtls_ssl_suite_get_key_exchange( ciphersuite_info )
|
||||||
== MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
|
== MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA )
|
||||||
{
|
{
|
||||||
((void) ret);
|
ret = uECC_shared_secret( ssl->handshake->ecdh_peerkey,
|
||||||
|
|
||||||
if( !uECC_shared_secret( ssl->handshake->ecdh_peerkey,
|
|
||||||
ssl->handshake->ecdh_privkey,
|
ssl->handshake->ecdh_privkey,
|
||||||
ssl->handshake->premaster ) )
|
ssl->handshake->premaster );
|
||||||
{
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
|
if( ret != UECC_SUCCESS )
|
||||||
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
||||||
}
|
|
||||||
|
|
||||||
ssl->handshake->pmslen = NUM_ECC_BYTES;
|
ssl->handshake->pmslen = NUM_ECC_BYTES;
|
||||||
}
|
}
|
||||||
|
@ -2168,14 +2167,13 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
|
||||||
size_t zlen;
|
size_t zlen;
|
||||||
|
|
||||||
#if defined(MBEDTLS_USE_TINYCRYPT)
|
#if defined(MBEDTLS_USE_TINYCRYPT)
|
||||||
((void) ret);
|
ret = uECC_shared_secret( ssl->handshake->ecdh_peerkey,
|
||||||
|
|
||||||
if( !uECC_shared_secret( ssl->handshake->ecdh_peerkey,
|
|
||||||
ssl->handshake->ecdh_privkey,
|
ssl->handshake->ecdh_privkey,
|
||||||
p + 2 ) )
|
p + 2 );
|
||||||
{
|
if( ret == UECC_FAULT_DETECTED )
|
||||||
|
return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
|
||||||
|
if( ret != UECC_SUCCESS )
|
||||||
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
|
||||||
}
|
|
||||||
|
|
||||||
zlen = NUM_ECC_BYTES;
|
zlen = NUM_ECC_BYTES;
|
||||||
#else /* MBEDTLS_USE_TINYCRYPT */
|
#else /* MBEDTLS_USE_TINYCRYPT */
|
||||||
|
|
|
@ -36,7 +36,7 @@ static int pk_genkey( mbedtls_pk_context *pk )
|
||||||
|
|
||||||
ret = uECC_make_key( mbedtls_pk_uecc( *pk )->public_key,
|
ret = uECC_make_key( mbedtls_pk_uecc( *pk )->public_key,
|
||||||
mbedtls_pk_uecc( *pk )->private_key );
|
mbedtls_pk_uecc( *pk )->private_key );
|
||||||
if( ret == 0 )
|
if( ret != UECC_SUCCESS )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
|
|
|
@ -137,7 +137,7 @@ void pk_parse_keyfile_ec( char * key_file, char * password, int result )
|
||||||
uecckey = mbedtls_pk_uecc( ctx );
|
uecckey = mbedtls_pk_uecc( ctx );
|
||||||
TEST_ASSERT( uECC_valid_public_key( uecckey->public_key ) == 0 );
|
TEST_ASSERT( uECC_valid_public_key( uecckey->public_key ) == 0 );
|
||||||
TEST_ASSERT( uECC_compute_public_key( uecckey->private_key,
|
TEST_ASSERT( uECC_compute_public_key( uecckey->private_key,
|
||||||
tmp_pubkey ) != 0 );
|
tmp_pubkey ) == UECC_SUCCESS );
|
||||||
TEST_ASSERT( memcmp( tmp_pubkey, uecckey->public_key,
|
TEST_ASSERT( memcmp( tmp_pubkey, uecckey->public_key,
|
||||||
sizeof( tmp_pubkey ) ) == 0 );
|
sizeof( tmp_pubkey ) ) == 0 );
|
||||||
#endif /* MBEDTLS_USE_TINYCRYPT */
|
#endif /* MBEDTLS_USE_TINYCRYPT */
|
||||||
|
|
|
@ -23,13 +23,13 @@ void test_ecdh()
|
||||||
|
|
||||||
uECC_set_rng( &uecc_rng_wrapper );
|
uECC_set_rng( &uecc_rng_wrapper );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_make_key( public1, private1 ) != 0 );
|
TEST_ASSERT( uECC_make_key( public1, private1 ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_make_key( public2, private2 ) != 0 );
|
TEST_ASSERT( uECC_make_key( public2, private2 ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_shared_secret( public2, private1, secret1 ) != 0 );
|
TEST_ASSERT( uECC_shared_secret( public2, private1, secret1 ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_shared_secret( public1, private2, secret2 ) != 0 );
|
TEST_ASSERT( uECC_shared_secret( public1, private2, secret2 ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( memcmp( secret1, secret2, sizeof( secret1 ) ) == 0 );
|
TEST_ASSERT( memcmp( secret1, secret2, sizeof( secret1 ) ) == 0 );
|
||||||
}
|
}
|
||||||
|
@ -47,9 +47,9 @@ void test_ecdsa()
|
||||||
|
|
||||||
TEST_ASSERT( rnd_std_rand( NULL, hash, NUM_ECC_BYTES ) == 0 );
|
TEST_ASSERT( rnd_std_rand( NULL, hash, NUM_ECC_BYTES ) == 0 );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_make_key( public, private ) != 0 );
|
TEST_ASSERT( uECC_make_key( public, private ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_sign( private, hash, sizeof( hash ), sig ) != 0 );
|
TEST_ASSERT( uECC_sign( private, hash, sizeof( hash ), sig ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_verify( public, hash, sizeof( hash ), sig ) == UECC_SUCCESS );
|
TEST_ASSERT( uECC_verify( public, hash, sizeof( hash ), sig ) == UECC_SUCCESS );
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,9 @@ void ecdh_primitive_testvec( data_t * private1, data_t * xA_str,
|
||||||
memcpy( public2 + NUM_ECC_BYTES, yB_str->x, yB_str->len );
|
memcpy( public2 + NUM_ECC_BYTES, yB_str->x, yB_str->len );
|
||||||
|
|
||||||
// Compute shared secrets and compare to test vector secret
|
// Compute shared secrets and compare to test vector secret
|
||||||
TEST_ASSERT( uECC_shared_secret( public2, private1->x, secret1 ) != 0 );
|
TEST_ASSERT( uECC_shared_secret( public2, private1->x, secret1 ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( uECC_shared_secret( public1, private2->x, secret2 ) != 0 );
|
TEST_ASSERT( uECC_shared_secret( public1, private2->x, secret2 ) == UECC_SUCCESS );
|
||||||
|
|
||||||
TEST_ASSERT( memcmp( secret1, secret2, sizeof( secret1 ) ) == 0 );
|
TEST_ASSERT( memcmp( secret1, secret2, sizeof( secret1 ) ) == 0 );
|
||||||
TEST_ASSERT( memcmp( secret1, z_str->x, sizeof( secret1 ) ) == 0 );
|
TEST_ASSERT( memcmp( secret1, z_str->x, sizeof( secret1 ) ) == 0 );
|
||||||
|
|
|
@ -1021,16 +1021,16 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||||
wordcount_t num_words = NUM_ECC_WORDS;
|
wordcount_t num_words = NUM_ECC_WORDS;
|
||||||
uECC_word_t carry;
|
uECC_word_t carry;
|
||||||
uECC_word_t *initial_Z = 0;
|
uECC_word_t *initial_Z = 0;
|
||||||
int r;
|
int r = UECC_FAULT_DETECTED;
|
||||||
|
|
||||||
/* Protect against faults modifying curve paremeters in flash */
|
/* Protect against faults modifying curve paremeters in flash */
|
||||||
if (uECC_check_curve_integrity() != 0) {
|
if (uECC_check_curve_integrity() != 0) {
|
||||||
return 0;
|
return UECC_FAULT_DETECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Protects against invalid curves attacks */
|
/* Protects against invalid curve attacks */
|
||||||
if (uECC_valid_point(point) != 0 ) {
|
if (uECC_valid_point(point) != 0 ) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Regularize the bitcount for the private key so that attackers cannot use a
|
/* Regularize the bitcount for the private key so that attackers cannot use a
|
||||||
|
@ -1041,7 +1041,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||||
* protect against side-channel attacks such as Template SPA */
|
* protect against side-channel attacks such as Template SPA */
|
||||||
if (g_rng_function) {
|
if (g_rng_function) {
|
||||||
if (!uECC_generate_random_int(k2[carry], curve_p, num_words)) {
|
if (!uECC_generate_random_int(k2[carry], curve_p, num_words)) {
|
||||||
r = 0;
|
r = UECC_FAILURE;
|
||||||
goto clear_and_out;
|
goto clear_and_out;
|
||||||
}
|
}
|
||||||
initial_Z = k2[carry];
|
initial_Z = k2[carry];
|
||||||
|
@ -1052,17 +1052,17 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||||
/* Protect against fault injections that would make the resulting
|
/* Protect against fault injections that would make the resulting
|
||||||
* point not lie on the intended curve */
|
* point not lie on the intended curve */
|
||||||
if (uECC_valid_point(result) != 0 ) {
|
if (uECC_valid_point(result) != 0 ) {
|
||||||
r = 0;
|
r = UECC_FAULT_DETECTED;
|
||||||
goto clear_and_out;
|
goto clear_and_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Protect against faults modifying curve paremeters in flash */
|
/* Protect against faults modifying curve paremeters in flash */
|
||||||
if (uECC_check_curve_integrity() != 0) {
|
if (uECC_check_curve_integrity() != 0) {
|
||||||
r = 0;
|
r = UECC_FAULT_DETECTED;
|
||||||
goto clear_and_out;
|
goto clear_and_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = 1;
|
r = UECC_SUCCESS;
|
||||||
|
|
||||||
clear_and_out:
|
clear_and_out:
|
||||||
/* erasing temporary buffer used to store secret: */
|
/* erasing temporary buffer used to store secret: */
|
||||||
|
@ -1176,7 +1176,7 @@ int uECC_valid_public_key(const uint8_t *public_key)
|
||||||
|
|
||||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
|
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
uECC_word_t _private[NUM_ECC_WORDS];
|
uECC_word_t _private[NUM_ECC_WORDS];
|
||||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||||
|
|
||||||
|
@ -1187,23 +1187,24 @@ int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
|
||||||
|
|
||||||
/* Make sure the private key is in the range [1, n-1]. */
|
/* Make sure the private key is in the range [1, n-1]. */
|
||||||
if (uECC_vli_isZero(_private)) {
|
if (uECC_vli_isZero(_private)) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uECC_vli_cmp(curve_n, _private) != 1) {
|
if (uECC_vli_cmp(curve_n, _private) != 1) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute public key. */
|
/* Compute public key. */
|
||||||
if (!EccPoint_compute_public_key(_public, _private)) {
|
ret = EccPoint_compute_public_key(_public, _private);
|
||||||
return 0;
|
if (ret != UECC_SUCCESS) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
|
uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
|
||||||
uECC_vli_nativeToBytes(
|
uECC_vli_nativeToBytes(
|
||||||
public_key +
|
public_key +
|
||||||
NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
|
NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
|
||||||
return 1;
|
return UECC_SUCCESS;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
typedef int mbedtls_dummy_tinycrypt_def;
|
typedef int mbedtls_dummy_tinycrypt_def;
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||||
unsigned int *d)
|
unsigned int *d)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
uECC_word_t _private[NUM_ECC_WORDS];
|
uECC_word_t _private[NUM_ECC_WORDS];
|
||||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||||
|
|
||||||
|
@ -85,7 +85,10 @@ int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||||
mbedtls_platform_memcpy (_private, d, NUM_ECC_BYTES);
|
mbedtls_platform_memcpy (_private, d, NUM_ECC_BYTES);
|
||||||
|
|
||||||
/* Computing public-key from private: */
|
/* Computing public-key from private: */
|
||||||
if (EccPoint_compute_public_key(_public, _private)) {
|
ret = EccPoint_compute_public_key(_public, _private);
|
||||||
|
if (ret != UECC_SUCCESS) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Converting buffers to correct bit order: */
|
/* Converting buffers to correct bit order: */
|
||||||
uECC_vli_nativeToBytes(private_key,
|
uECC_vli_nativeToBytes(private_key,
|
||||||
|
@ -98,17 +101,16 @@ int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||||
NUM_ECC_BYTES,
|
NUM_ECC_BYTES,
|
||||||
_public + NUM_ECC_WORDS);
|
_public + NUM_ECC_WORDS);
|
||||||
|
|
||||||
|
exit:
|
||||||
/* erasing temporary buffer used to store secret: */
|
/* erasing temporary buffer used to store secret: */
|
||||||
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
||||||
|
|
||||||
return 1;
|
return ret;
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
uECC_word_t _random[NUM_ECC_WORDS * 2];
|
uECC_word_t _random[NUM_ECC_WORDS * 2];
|
||||||
uECC_word_t _private[NUM_ECC_WORDS];
|
uECC_word_t _private[NUM_ECC_WORDS];
|
||||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||||
|
@ -119,14 +121,19 @@ int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
||||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||||
if (!rng_function ||
|
if (!rng_function ||
|
||||||
!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
|
/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
|
||||||
uECC_vli_mmod(_private, _random, curve_n);
|
uECC_vli_mmod(_private, _random, curve_n);
|
||||||
|
|
||||||
/* Computing public-key from private: */
|
/* Computing public-key from private: */
|
||||||
if (EccPoint_compute_public_key(_public, _private)) {
|
ret = EccPoint_compute_public_key(_public, _private);
|
||||||
|
/* don't try again if a fault was detected */
|
||||||
|
if (ret == UECC_FAULT_DETECTED) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ret == UECC_SUCCESS) {
|
||||||
|
|
||||||
/* Converting buffers to correct bit order: */
|
/* Converting buffers to correct bit order: */
|
||||||
uECC_vli_nativeToBytes(private_key,
|
uECC_vli_nativeToBytes(private_key,
|
||||||
|
@ -142,10 +149,10 @@ int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
||||||
/* erasing temporary buffer that stored secret: */
|
/* erasing temporary buffer that stored secret: */
|
||||||
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
||||||
|
|
||||||
return 1;
|
return UECC_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||||
|
|
|
@ -122,12 +122,12 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||||
/* Make sure 0 < k < curve_n */
|
/* Make sure 0 < k < curve_n */
|
||||||
if (uECC_vli_isZero(k) ||
|
if (uECC_vli_isZero(k) ||
|
||||||
uECC_vli_cmp(curve_n, k) != 1) {
|
uECC_vli_cmp(curve_n, k) != 1) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = EccPoint_mult_safer(p, curve_G, k);
|
r = EccPoint_mult_safer(p, curve_G, k);
|
||||||
if (r == 0 || uECC_vli_isZero(p)) {
|
if (r != UECC_SUCCESS) {
|
||||||
return 0;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If an RNG function was specified, get a random number
|
/* If an RNG function was specified, get a random number
|
||||||
|
@ -137,7 +137,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||||
tmp[0] = 1;
|
tmp[0] = 1;
|
||||||
}
|
}
|
||||||
else if (!uECC_generate_random_int(tmp, curve_n, num_n_words)) {
|
else if (!uECC_generate_random_int(tmp, curve_n, num_n_words)) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent side channel analysis of uECC_vli_modInv() to determine
|
/* Prevent side channel analysis of uECC_vli_modInv() to determine
|
||||||
|
@ -159,16 +159,17 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||||
uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */
|
uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */
|
||||||
uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */
|
uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */
|
||||||
if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) {
|
if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s);
|
uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s);
|
||||||
return 1;
|
return UECC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||||
unsigned hash_size, uint8_t *signature)
|
unsigned hash_size, uint8_t *signature)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
uECC_word_t _random[2*NUM_ECC_WORDS];
|
uECC_word_t _random[2*NUM_ECC_WORDS];
|
||||||
uECC_word_t k[NUM_ECC_WORDS];
|
uECC_word_t k[NUM_ECC_WORDS];
|
||||||
uECC_word_t tries;
|
uECC_word_t tries;
|
||||||
|
@ -178,17 +179,23 @@ int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||||
if (!rng_function ||
|
if (!rng_function ||
|
||||||
!rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
!rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||||
return 0;
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
|
// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
|
||||||
uECC_vli_mmod(k, _random, curve_n);
|
uECC_vli_mmod(k, _random, curve_n);
|
||||||
|
|
||||||
if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature)) {
|
r = uECC_sign_with_k(private_key, message_hash, hash_size, k, signature);
|
||||||
return 1;
|
/* don't keep trying if a fault was detected */
|
||||||
|
if (r == UECC_FAULT_DETECTED) {
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
if (r == UECC_SUCCESS) {
|
||||||
|
return UECC_SUCCESS;
|
||||||
}
|
}
|
||||||
return 0;
|
/* else keep trying */
|
||||||
|
}
|
||||||
|
return UECC_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bitcount_t smax(bitcount_t a, bitcount_t b)
|
static bitcount_t smax(bitcount_t a, bitcount_t b)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue