Coverity (#28)
* stratum_server: resolve CID 210144 (UNINIT_CTOR)
* stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_blockchain_update_listener, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro
A temporary substition for what I hope will eventually be a full-fledged
exception-dispatcher (class-based, not macro).
* stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_protocol_handler, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT)
The potential to throw exists within guarded_critical_region_t, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger, del_connection, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: move macros to *top* of file
so they can be used *within* this file.
* daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT)
The potential to throw exists within log_space, and any paths involving
the logger (including CATCH_ENTRY_*).
* daemon: return cstdlib proper types in main
* simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT)
CID: 210082
CID: 210086
CID: 210096
CID: 210147
CID: 210149
CID: 210150
The potential to throw exists throughout various paths in main.
* simplewallet: return cstdlib proper types in main
* simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, and any paths
involving the logger (including CATCH_ENTRY_*).
* conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT)
CID: 210038
CID: 210047
CID: 210108
CID: 210122
CID: 210157
The potential to throw exists throughout various paths in main.
* conn_tool: return cstdlib proper types in main
* miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT)
The potential to throw exists within deinit, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT)
The potential to throw exists within boost microsec_clock::localtime(),
and any paths involving the logger (including CATCH_ENTRY_*).
* db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT)
The potential to throw exists within close(), including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT)
The potential to throw exists within several paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210064
CID: 210093
CID: 210136
CID: 210139
The potential to throw exists within m_func(), including any paths
involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210072
CID: 210094
CID: 210116
CID: 210141
The potential to throw exists within m_cache.clear(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT)
The potential to throw exists within shutdown(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT)
The potential to throw exists within unlock(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: http_base: resolve CID 210176 (UNINIT_CTOR)
* p2p: net_node: resolve CID 210173 (UNINIT_CTOR)
* epee: net_helper: resolve CID 210138 (UNINIT_CTOR)
* p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR)
* currency_basic: resolve CID 210117 (UNINIT_CTOR)
* epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR)
CID: 210040
CID: 210090
CID: 210105
* simplewallet: resolve CID 210103 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR)
* json_archive: resolve CID 210087 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR)
* miniupnp_helper: resolve CID 210037 (UNINIT_CTOR)
* crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN)
* wallet2: resolve CID 210041 (CHECKED_RETURN)
* epee: misc_log_ex: resolve CID 210127 (DEADCODE)
* epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE)
CID: 210167
CID: 210170
CID: 210180
* p2p: net_node: resolve CID 210065 (PASS_BY_VALUE)
* epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE)
* epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE)
* epee: misc_log_ex: add NESTED_*_ENTRY macros
* simplewallet: use NESTED_*_ENTRY in message_writer dtor
* stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor
* stratum_protocol_handler: use NESTED_*_ENTRY in dtor
* lmdb_db_backend: use NESTED_*_ENTRY in dtor
* epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210088
CID: 210106
CID: 210164
CID: 210179
The potential to throw exists within various paths, including any
paths involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: use NESTED_*_ENTRY in dtor
* miniupnp_helper: use NESTED_*_ENTRY in dtor
* epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor
* epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors
* epee: net_helper: use NESTED_*_ENTRY in dtor
* epee: profile_tools: use NESTED_*_ENTRY in dtors
* epee: misc_language: use NESTED_*_ENTRY in dtor
* epee: syncobj: use NESTED_*_ENTRY in dtor
* zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
// Copyright (c) 2014-2019 Zano Project
2018-12-27 18:50:45 +03:00
// Copyright (c) 2014-2018 The Louisdor Project
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include <alloca.h>
# include <cassert>
# include <cstddef>
# include <cstdint>
# include <cstdlib>
# include <cstring>
# include <memory>
# include <mutex>
# include "common/varint.h"
# include "warnings.h"
# include "crypto.h"
# include "hash.h"
2019-05-21 21:22:30 +03:00
# if !defined(NDEBUG)
# define crypto_assert(expression) assert(expression)
# else
# define crypto_assert(expression) ((void)0)
# endif
2018-12-27 18:50:45 +03:00
namespace crypto {
DISABLE_GCC_AND_CLANG_WARNING ( strict - aliasing )
2019-05-23 05:07:59 +03:00
const unsigned char Z_ [ 32 ] = { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
2018-12-27 18:50:45 +03:00
const unsigned char I_ [ 32 ] = { 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
const unsigned char L_ [ 32 ] = { 0xed , 0xd3 , 0xf5 , 0x5c , 0x1a , 0x63 , 0x12 , 0x58 , 0xd6 , 0x9c , 0xf7 , 0xa2 , 0xde , 0xf9 , 0xde , 0x14 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 } ;
2019-05-23 05:07:59 +03:00
const key_image Z = * reinterpret_cast < const key_image * > ( & Z_ ) ;
2018-12-27 18:50:45 +03:00
const key_image I = * reinterpret_cast < const key_image * > ( & I_ ) ;
const key_image L = * reinterpret_cast < const key_image * > ( & L_ ) ;
struct random_init_singleton
{
random_init_singleton ( )
{
grant_random_initialize ( ) ;
}
} ;
random_init_singleton init_rand ; //place initializer here to avoid grant_random_initialize first call after threads will be possible(local static variables init is not thread-safe)
using std : : abort ;
using std : : int32_t ;
using std : : int64_t ;
using std : : lock_guard ;
using std : : mutex ;
using std : : size_t ;
using std : : uint32_t ;
using std : : uint64_t ;
extern " C " {
# include "crypto-ops.h"
# include "random.h"
}
mutex random_lock ;
static inline unsigned char * operator & ( ec_point & point ) {
return & reinterpret_cast < unsigned char & > ( point ) ;
}
static inline const unsigned char * operator & ( const ec_point & point ) {
return & reinterpret_cast < const unsigned char & > ( point ) ;
}
static inline unsigned char * operator & ( ec_scalar & scalar ) {
return & reinterpret_cast < unsigned char & > ( scalar ) ;
}
static inline const unsigned char * operator & ( const ec_scalar & scalar ) {
return & reinterpret_cast < const unsigned char & > ( scalar ) ;
}
static inline void random_scalar ( ec_scalar & res ) {
unsigned char tmp [ 64 ] ;
generate_random_bytes ( 64 , tmp ) ;
sc_reduce ( tmp ) ;
memcpy ( & res , tmp , 32 ) ;
}
2020-05-02 23:59:37 +03:00
void crypto_ops : : keys_from_default ( const unsigned char * a_part , public_key & pub , secret_key & sec , size_t keys_seed_binary_size )
{
unsigned char tmp [ 64 ] = { 0 } ;
2018-12-27 18:50:45 +03:00
2020-05-02 23:59:37 +03:00
if ( ! ( sizeof ( tmp ) > = keys_seed_binary_size ) )
{
throw std : : runtime_error ( " size mismatch " ) ;
}
2018-12-27 18:50:45 +03:00
2020-05-02 23:59:37 +03:00
memcpy ( tmp , a_part , keys_seed_binary_size ) ;
2018-12-27 18:50:45 +03:00
2020-05-02 23:59:37 +03:00
cn_fast_hash ( tmp , 32 , ( char * ) & tmp [ 32 ] ) ;
2018-12-27 18:50:45 +03:00
2020-05-02 23:59:37 +03:00
sc_reduce ( tmp ) ;
memcpy ( & sec , tmp , 32 ) ;
ge_p3 point ;
ge_scalarmult_base ( & point , & sec ) ;
ge_p3_tobytes ( & pub , & point ) ;
}
2018-12-27 18:50:45 +03:00
2020-05-02 23:59:37 +03:00
void crypto_ops : : generate_seed_keys ( public_key & pub , secret_key & sec , std : : vector < unsigned char > & keys_seed_binary , size_t keys_seed_binary_size )
2018-12-27 18:50:45 +03:00
{
2020-05-02 23:59:37 +03:00
keys_seed_binary . resize ( keys_seed_binary_size , 0 ) ;
generate_random_bytes ( keys_seed_binary_size , keys_seed_binary . data ( ) ) ;
keys_from_default ( keys_seed_binary . data ( ) , pub , sec , keys_seed_binary_size ) ;
2018-12-27 18:50:45 +03:00
}
static inline void hash_to_scalar ( const void * data , size_t length , ec_scalar & res )
{
cn_fast_hash ( data , length , reinterpret_cast < hash & > ( res ) ) ;
sc_reduce32 ( & res ) ;
}
void crypto_ops : : generate_keys ( public_key & pub , secret_key & sec ) {
lock_guard < mutex > lock ( random_lock ) ;
ge_p3 point ;
random_scalar ( sec ) ;
ge_scalarmult_base ( & point , & sec ) ;
ge_p3_tobytes ( & pub , & point ) ;
}
void crypto_ops : : dependent_key ( const secret_key & first , secret_key & second )
{
hash_to_scalar ( & first , 32 , second ) ;
if ( sc_check ( ( unsigned char * ) & second ) ! = 0 )
throw std : : runtime_error ( " Failed to derive key " ) ;
}
bool crypto_ops : : check_key ( const public_key & key ) {
ge_p3 point ;
return ge_frombytes_vartime ( & point , & key ) = = 0 ;
}
/*
Fix discovered by Monero Lab and suggested by " fluffypony " ( bitcointalk . org )
*/
key_image scalarmult_key ( const key_image & P , const key_image & a )
{
ge_p3 A = ge_p3 ( ) ;
ge_p2 R = ge_p2 ( ) ;
Coverity (#28)
* stratum_server: resolve CID 210144 (UNINIT_CTOR)
* stratum_server: resolve CID 210042/210085/210104 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_blockchain_update_listener, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: misc_log_ex: create CATCH_ENTRY_NO_RETURN macro
A temporary substition for what I hope will eventually be a full-fledged
exception-dispatcher (class-based, not macro).
* stratum_server: resolve CID 210080/210084/210089 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger,
remove_protocol_handler, and any paths involving the logger
(including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210140/210182/210165 (UNCAUGHT_EXCEPT)
The potential to throw exists within guarded_critical_region_t, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: levin_protocol_handler_async: resolve CID 210110/210119/210155 (UNCAUGHT_EXCEPT)
The potential to throw exists within the logger, del_connection, and any
paths involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: move macros to *top* of file
so they can be used *within* this file.
* daemon: resolve CID 210069/210092/210166 (UNCAUGHT_EXCEPT)
The potential to throw exists within log_space, and any paths involving
the logger (including CATCH_ENTRY_*).
* daemon: return cstdlib proper types in main
* simplewallet: resolve 6 different CIDs (UNCAUGHT_EXCEPT)
CID: 210082
CID: 210086
CID: 210096
CID: 210147
CID: 210149
CID: 210150
The potential to throw exists throughout various paths in main.
* simplewallet: return cstdlib proper types in main
* simplewallet: resolve CID 210128/210160 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, and any paths
involving the logger (including CATCH_ENTRY_*).
* conn_tool: resolve 5 different CIDs (UNCAUGHT_EXCEPT)
CID: 210038
CID: 210047
CID: 210108
CID: 210122
CID: 210157
The potential to throw exists throughout various paths in main.
* conn_tool: return cstdlib proper types in main
* miniupnp_helper: resolve CID 210050 (UNCAUGHT_EXCEPT)
The potential to throw exists within deinit, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210055 (UNCAUGHT_EXCEPT)
The potential to throw exists within boost microsec_clock::localtime(),
and any paths involving the logger (including CATCH_ENTRY_*).
* db_backend_lmdb: resolve CID 210056/210133 (UNCAUGHT_EXCEPT)
The potential to throw exists within close(), including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_log_ex: resolve CID 210060/210124 (UNCAUGHT_EXCEPT)
The potential to throw exists within several paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: misc_language: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210064
CID: 210093
CID: 210136
CID: 210139
The potential to throw exists within m_func(), including any paths
involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210072
CID: 210094
CID: 210116
CID: 210141
The potential to throw exists within m_cache.clear(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: net_helper: resolve CID 210100 (UNCAUGHT_EXCEPT)
The potential to throw exists within shutdown(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: syncobj: resolve CID 210123 (UNCAUGHT_EXCEPT)
The potential to throw exists within unlock(), including any
paths involving the logger (including CATCH_ENTRY_*).
* epee: profile_tools: resolve CID 210145/210154 (UNCAUGHT_EXCEPT)
The potential to throw exists within various paths, including any paths
involving the logger (including CATCH_ENTRY_*).
* epee: http_base: resolve CID 210176 (UNINIT_CTOR)
* p2p: net_node: resolve CID 210173 (UNINIT_CTOR)
* epee: net_helper: resolve CID 210138 (UNINIT_CTOR)
* p2p: net_peerlist: resolve CID 210137 (UNINIT_CTOR)
* currency_basic: resolve CID 210117 (UNINIT_CTOR)
* epee: abstract_tcp_server2: resolve 3 CIDs (UNINIT_CTOR)
CID: 210040
CID: 210090
CID: 210105
* simplewallet: resolve CID 210103 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210091 (UNINIT_CTOR)
* json_archive: resolve CID 210087 (UNINIT_CTOR)
* epee: levin_protocol_handler_async: resolve CID 210073 (UNINIT_CTOR)
* miniupnp_helper: resolve CID 210037 (UNINIT_CTOR)
* crypto: ge_frombytes_vartime: resolve CID 210142 (CHECKED_RETURN)
* wallet2: resolve CID 210041 (CHECKED_RETURN)
* epee: misc_log_ex: resolve CID 210127 (DEADCODE)
* epee: levin_protocol_handler_sync: resolve 3 CIDs (PASS_BY_VALUE)
CID: 210167
CID: 210170
CID: 210180
* p2p: net_node: resolve CID 210065 (PASS_BY_VALUE)
* epee: levin_abstract_invoke2: resolve CID 210049 (PASS_BY_VALUE)
* epee: abstract_tcp_server2: resolve CID 210045 (PASS_BY_VALUE)
* epee: misc_log_ex: add NESTED_*_ENTRY macros
* simplewallet: use NESTED_*_ENTRY in message_writer dtor
* stratum_protocol_handler_config: use NESTED_*_ENTRY in dtor
* stratum_protocol_handler: use NESTED_*_ENTRY in dtor
* lmdb_db_backend: use NESTED_*_ENTRY in dtor
* epee: abstract_tcp_server2: resolve 4 CIDs (UNCAUGHT_EXCEPT)
CID: 210088
CID: 210106
CID: 210164
CID: 210179
The potential to throw exists within various paths, including any
paths involving the logger (including CATCH_ENTRY_*).
* db_abstract_accessor: use NESTED_*_ENTRY in dtor
* miniupnp_helper: use NESTED_*_ENTRY in dtor
* epee: misc_log_ex: use NESTED_*_ENTRY in log_frame dtor
* epee: levin_protocol_handler_async: use NESTED_*_ENTRY in dtors
* epee: net_helper: use NESTED_*_ENTRY in dtor
* epee: profile_tools: use NESTED_*_ENTRY in dtors
* epee: misc_language: use NESTED_*_ENTRY in dtor
* epee: syncobj: use NESTED_*_ENTRY in dtor
* zano: license contact w/ zano.org email instead of sekreta.org email
2019-05-20 09:32:36 +00:00
if ( ge_frombytes_vartime ( & A , reinterpret_cast < const unsigned char * > ( & P ) ) ! = 0 )
2019-05-23 05:07:59 +03:00
return Z ;
2018-12-27 18:50:45 +03:00
ge_scalarmult ( & R , reinterpret_cast < const unsigned char * > ( & a ) , & A ) ;
key_image a_p = key_image ( ) ;
ge_tobytes ( reinterpret_cast < unsigned char * > ( & a_p ) , & R ) ;
return a_p ;
}
bool crypto_ops : : validate_key_image ( const key_image & ki )
{
if ( ! ( scalarmult_key ( ki , L ) = = I ) )
return false ;
2019-05-23 05:07:59 +03:00
2018-12-27 18:50:45 +03:00
return true ;
}
bool crypto_ops : : secret_key_to_public_key ( const secret_key & sec , public_key & pub ) {
ge_p3 point ;
if ( sc_check ( & sec ) ! = 0 ) {
return false ;
}
ge_scalarmult_base ( & point , & sec ) ;
ge_p3_tobytes ( & pub , & point ) ;
return true ;
}
bool crypto_ops : : generate_key_derivation ( const public_key & key1 , const secret_key & key2 , key_derivation & derivation ) {
ge_p3 point ;
ge_p2 point2 ;
ge_p1p1 point3 ;
2019-05-21 21:22:30 +03:00
crypto_assert ( sc_check ( & key2 ) = = 0 ) ;
2018-12-27 18:50:45 +03:00
if ( ge_frombytes_vartime ( & point , & key1 ) ! = 0 ) {
return false ;
}
ge_scalarmult ( & point2 , & key2 , & point ) ;
ge_mul8 ( & point3 , & point2 ) ;
ge_p1p1_to_p2 ( & point2 , & point3 ) ;
ge_tobytes ( & derivation , & point2 ) ;
return true ;
}
2022-06-28 22:15:18 +02:00
void crypto_ops : : derivation_to_scalar ( const key_derivation & derivation , size_t output_index , ec_scalar & res )
{
2018-12-27 18:50:45 +03:00
struct {
key_derivation derivation ;
char output_index [ ( sizeof ( size_t ) * 8 + 6 ) / 7 ] ;
} buf ;
char * end = buf . output_index ;
buf . derivation = derivation ;
tools : : write_varint ( end , output_index ) ;
2019-05-21 21:22:30 +03:00
if ( ! ( end < = buf . output_index + sizeof buf . output_index ) )
{
crypto_assert ( false ) ;
return ;
}
2018-12-27 18:50:45 +03:00
hash_to_scalar ( & buf , end - reinterpret_cast < char * > ( & buf ) , res ) ;
}
bool crypto_ops : : derive_public_key ( const key_derivation & derivation , size_t output_index ,
const public_key & base , public_key & derived_key ) {
ec_scalar scalar ;
ge_p3 point1 ;
ge_p3 point2 ;
ge_cached point3 ;
ge_p1p1 point4 ;
ge_p2 point5 ;
if ( ge_frombytes_vartime ( & point1 , & base ) ! = 0 ) {
return false ;
}
derivation_to_scalar ( derivation , output_index , scalar ) ;
ge_scalarmult_base ( & point2 , & scalar ) ;
ge_p3_to_cached ( & point3 , & point2 ) ;
ge_add ( & point4 , & point1 , & point3 ) ;
ge_p1p1_to_p2 ( & point5 , & point4 ) ;
ge_tobytes ( & derived_key , & point5 ) ;
return true ;
}
void crypto_ops : : derive_secret_key ( const key_derivation & derivation , size_t output_index ,
const secret_key & base , secret_key & derived_key ) {
ec_scalar scalar ;
2019-05-21 21:22:30 +03:00
crypto_assert ( sc_check ( & base ) = = 0 ) ;
2018-12-27 18:50:45 +03:00
derivation_to_scalar ( derivation , output_index , scalar ) ;
sc_add ( & derived_key , & base , & scalar ) ;
}
struct s_comm {
hash h ;
ec_point key ;
ec_point comm ;
} ;
void crypto_ops : : generate_signature ( const hash & prefix_hash , const public_key & pub , const secret_key & sec , signature & sig ) {
lock_guard < mutex > lock ( random_lock ) ;
ge_p3 tmp3 ;
ec_scalar k ;
s_comm buf ;
# if !defined(NDEBUG)
{
ge_p3 t ;
public_key t2 ;
2019-05-21 21:22:30 +03:00
crypto_assert ( sc_check ( & sec ) = = 0 ) ;
2018-12-27 18:50:45 +03:00
ge_scalarmult_base ( & t , & sec ) ;
ge_p3_tobytes ( & t2 , & t ) ;
2019-05-21 21:22:30 +03:00
crypto_assert ( pub = = t2 ) ;
2018-12-27 18:50:45 +03:00
}
# endif
buf . h = prefix_hash ;
buf . key = pub ;
random_scalar ( k ) ;
ge_scalarmult_base ( & tmp3 , & k ) ;
ge_p3_tobytes ( & buf . comm , & tmp3 ) ;
hash_to_scalar ( & buf , sizeof ( s_comm ) , sig . c ) ;
sc_mulsub ( & sig . r , & sig . c , & sec , & k ) ;
}
bool crypto_ops : : check_signature ( const hash & prefix_hash , const public_key & pub , const signature & sig ) {
ge_p2 tmp2 ;
ge_p3 tmp3 ;
ec_scalar c ;
s_comm buf ;
2019-05-21 21:22:30 +03:00
crypto_assert ( check_key ( pub ) ) ;
2018-12-27 18:50:45 +03:00
buf . h = prefix_hash ;
buf . key = pub ;
if ( ge_frombytes_vartime ( & tmp3 , & pub ) ! = 0 ) {
return false ;
}
if ( sc_check ( & sig . c ) ! = 0 | | sc_check ( & sig . r ) ! = 0 ) {
return false ;
}
ge_double_scalarmult_base_vartime ( & tmp2 , & sig . c , & tmp3 , & sig . r ) ;
ge_tobytes ( & buf . comm , & tmp2 ) ;
hash_to_scalar ( & buf , sizeof ( s_comm ) , c ) ;
sc_sub ( & c , & c , & sig . c ) ;
return sc_isnonzero ( & c ) = = 0 ;
}
static void hash_to_ec ( const public_key & key , ge_p3 & res ) {
hash h ;
ge_p2 point ;
ge_p1p1 point2 ;
cn_fast_hash ( std : : addressof ( key ) , sizeof ( public_key ) , h ) ;
ge_fromfe_frombytes_vartime ( & point , reinterpret_cast < const unsigned char * > ( & h ) ) ;
ge_mul8 ( & point2 , & point ) ;
ge_p1p1_to_p3 ( & res , & point2 ) ;
}
void crypto_ops : : generate_key_image ( const public_key & pub , const secret_key & sec , key_image & image ) {
ge_p3 point ;
ge_p2 point2 ;
2019-05-21 21:22:30 +03:00
crypto_assert ( sc_check ( & sec ) = = 0 ) ;
2018-12-27 18:50:45 +03:00
hash_to_ec ( pub , point ) ;
ge_scalarmult ( & point2 , & sec , & point ) ;
ge_tobytes ( & image , & point2 ) ;
}
2019-09-27 17:16:18 +02:00
PUSH_VS_WARNINGS
2018-12-27 18:50:45 +03:00
DISABLE_VS_WARNINGS ( 4200 )
2021-01-09 17:48:57 +03:00
struct rs_comm_entry
{
ec_point a , b ;
} ;
struct rs_comm
{
2018-12-27 18:50:45 +03:00
hash h ;
struct rs_comm_entry ab [ ] ;
} ;
2019-09-27 17:16:18 +02:00
POP_VS_WARNINGS
2018-12-27 18:50:45 +03:00
static inline size_t rs_comm_size ( size_t pubs_count ) {
return sizeof ( rs_comm ) + pubs_count * sizeof ( rs_comm_entry ) ;
}
void crypto_ops : : generate_ring_signature ( const hash & prefix_hash , const key_image & image ,
const public_key * const * pubs , size_t pubs_count ,
const secret_key & sec , size_t sec_index ,
signature * sig ) {
lock_guard < mutex > lock ( random_lock ) ;
size_t i ;
ge_p3 image_unp ;
ge_dsmp image_pre ;
ec_scalar sum , k , h ;
rs_comm * const buf = reinterpret_cast < rs_comm * > ( alloca ( rs_comm_size ( pubs_count ) ) ) ;
2019-05-21 21:22:30 +03:00
if ( ! ( sec_index < pubs_count ) )
{
crypto_assert ( false ) ;
return ;
}
2018-12-27 18:50:45 +03:00
# if !defined(NDEBUG)
{
ge_p3 t ;
public_key t2 ;
key_image t3 ;
2019-05-21 21:22:30 +03:00
crypto_assert ( sc_check ( & sec ) = = 0 ) ;
2018-12-27 18:50:45 +03:00
ge_scalarmult_base ( & t , & sec ) ;
ge_p3_tobytes ( & t2 , & t ) ;
2019-05-21 21:22:30 +03:00
crypto_assert ( * pubs [ sec_index ] = = t2 ) ;
2018-12-27 18:50:45 +03:00
generate_key_image ( * pubs [ sec_index ] , sec , t3 ) ;
2019-05-21 21:22:30 +03:00
crypto_assert ( image = = t3 ) ;
2018-12-27 18:50:45 +03:00
for ( i = 0 ; i < pubs_count ; i + + ) {
2019-05-21 21:22:30 +03:00
crypto_assert ( check_key ( * pubs [ i ] ) ) ;
2018-12-27 18:50:45 +03:00
}
}
# endif
if ( ge_frombytes_vartime ( & image_unp , & image ) ! = 0 ) {
abort ( ) ;
}
ge_dsm_precomp ( image_pre , & image_unp ) ;
sc_0 ( & sum ) ;
buf - > h = prefix_hash ;
for ( i = 0 ; i < pubs_count ; i + + ) {
ge_p2 tmp2 ;
ge_p3 tmp3 ;
if ( i = = sec_index ) {
random_scalar ( k ) ;
ge_scalarmult_base ( & tmp3 , & k ) ;
ge_p3_tobytes ( & buf - > ab [ i ] . a , & tmp3 ) ;
hash_to_ec ( * pubs [ i ] , tmp3 ) ;
ge_scalarmult ( & tmp2 , & k , & tmp3 ) ;
ge_tobytes ( & buf - > ab [ i ] . b , & tmp2 ) ;
} else {
random_scalar ( sig [ i ] . c ) ;
random_scalar ( sig [ i ] . r ) ;
if ( ge_frombytes_vartime ( & tmp3 , & * pubs [ i ] ) ! = 0 ) {
abort ( ) ;
}
ge_double_scalarmult_base_vartime ( & tmp2 , & sig [ i ] . c , & tmp3 , & sig [ i ] . r ) ;
ge_tobytes ( & buf - > ab [ i ] . a , & tmp2 ) ;
hash_to_ec ( * pubs [ i ] , tmp3 ) ;
ge_double_scalarmult_precomp_vartime ( & tmp2 , & sig [ i ] . r , & tmp3 , & sig [ i ] . c , image_pre ) ;
ge_tobytes ( & buf - > ab [ i ] . b , & tmp2 ) ;
sc_add ( & sum , & sum , & sig [ i ] . c ) ;
}
}
hash_to_scalar ( buf , rs_comm_size ( pubs_count ) , h ) ;
sc_sub ( & sig [ sec_index ] . c , & h , & sum ) ;
sc_mulsub ( & sig [ sec_index ] . r , & sig [ sec_index ] . c , & sec , & k ) ;
}
bool crypto_ops : : check_ring_signature ( const hash & prefix_hash , const key_image & image ,
const public_key * const * pubs , size_t pubs_count ,
const signature * sig ) {
size_t i ;
ge_p3 image_unp ;
ge_dsmp image_pre ;
ec_scalar sum , h ;
rs_comm * const buf = reinterpret_cast < rs_comm * > ( alloca ( rs_comm_size ( pubs_count ) ) ) ;
# if !defined(NDEBUG)
for ( i = 0 ; i < pubs_count ; i + + ) {
2019-05-21 21:22:30 +03:00
crypto_assert ( check_key ( * pubs [ i ] ) ) ;
2018-12-27 18:50:45 +03:00
}
# endif
if ( ge_frombytes_vartime ( & image_unp , & image ) ! = 0 ) {
return false ;
}
ge_dsm_precomp ( image_pre , & image_unp ) ;
sc_0 ( & sum ) ;
buf - > h = prefix_hash ;
for ( i = 0 ; i < pubs_count ; i + + ) {
ge_p2 tmp2 ;
ge_p3 tmp3 ;
if ( sc_check ( & sig [ i ] . c ) ! = 0 | | sc_check ( & sig [ i ] . r ) ! = 0 ) {
return false ;
}
if ( ge_frombytes_vartime ( & tmp3 , & * pubs [ i ] ) ! = 0 ) {
return false ;
}
2021-04-24 04:48:38 +03:00
ge_double_scalarmult_base_vartime ( & tmp2 , & sig [ i ] . c , & tmp3 , & sig [ i ] . r ) ; // L_i = r_i * G + c_i * P_i
2018-12-27 18:50:45 +03:00
ge_tobytes ( & buf - > ab [ i ] . a , & tmp2 ) ;
hash_to_ec ( * pubs [ i ] , tmp3 ) ;
2021-04-24 04:48:38 +03:00
ge_double_scalarmult_precomp_vartime ( & tmp2 , & sig [ i ] . r , & tmp3 , & sig [ i ] . c , image_pre ) ; // R_i = r_i * Hp(P_i) + c_i * I
2018-12-27 18:50:45 +03:00
ge_tobytes ( & buf - > ab [ i ] . b , & tmp2 ) ;
sc_add ( & sum , & sum , & sig [ i ] . c ) ;
}
hash_to_scalar ( buf , rs_comm_size ( pubs_count ) , h ) ;
sc_sub ( & h , & h , & sum ) ;
return sc_isnonzero ( & h ) = = 0 ;
}
2021-01-09 17:48:57 +03:00
} // namespace crypto