@ -37,79 +37,115 @@ void secp256k1_default_error_callback_fn(const char *str, void *data) {
return ;
}
static secp256k1_context * secp256k1_ctx = NULL ;
static void * secp256k1_ctx_buf = NULL ;
static size_t secp256k1_ctx_size = 0 ;
/// package: trezorcrypto.secp256k1_zkp
static const secp256k1_context * mod_trezorcrypto_secp256k1_context_create (
void ) {
if ( secp256k1_ctx = = NULL ) {
secp256k1_ctx_size = secp256k1_context_preallocated_size (
SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY ) ;
secp256k1_ctx_buf = m_new_maybe ( uint8_t , secp256k1_ctx_size ) ;
if ( ! secp256k1_ctx_buf ) {
mp_raise_ValueError ( " secp256k1_zkp context is too large " ) ;
}
secp256k1_ctx = secp256k1_context_preallocated_create (
secp256k1_ctx_buf , SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY ) ;
/// class Context:
/// """
/// Owns a secp256k1 context.
/// Can be allocated once and re-used between subsequent operations.
/// """
///
typedef struct _mp_obj_secp256k1_context_t {
mp_obj_base_t base ;
secp256k1_context * secp256k1_ctx ;
size_t secp256k1_ctx_size ;
uint8_t secp256k1_ctx_buf [ 0 ] ; // to be allocate via m_new_obj_var_maybe().
} mp_obj_secp256k1_context_t ;
uint8_t rand [ 32 ] ;
random_buffer ( rand , 32 ) ;
int ret = secp256k1_context_randomize ( secp256k1_ctx , rand ) ;
if ( ret ! = 1 ) {
mp_raise_msg ( & mp_type_RuntimeError , " secp256k1_context_randomize failed " ) ;
}
/// def __init__(self):
/// """
/// Allocate and initialize secp256k1_context.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_context_make_new (
const mp_obj_type_t * type , size_t n_args , size_t n_kw ,
const mp_obj_t * args ) {
mp_arg_check_num ( n_args , n_kw , 0 , 0 , false ) ;
const size_t secp256k1_ctx_size = secp256k1_context_preallocated_size (
SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY ) ;
mp_obj_secp256k1_context_t * o = m_new_obj_var_maybe (
mp_obj_secp256k1_context_t , uint8_t , secp256k1_ctx_size ) ;
if ( ! o ) {
mp_raise_ValueError ( " secp256k1_zkp context is too large " ) ;
}
o - > base . type = type ;
o - > secp256k1_ctx_size = secp256k1_ctx_size ;
o - > secp256k1_ctx = secp256k1_context_preallocated_create (
o - > secp256k1_ctx_buf , SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY ) ;
uint8_t rand [ 32 ] = { 0 } ;
random_buffer ( rand , 32 ) ;
int ret = secp256k1_context_randomize ( o - > secp256k1_ctx , rand ) ;
if ( ret ! = 1 ) {
mp_raise_msg ( & mp_type_RuntimeError , " secp256k1_context_randomize failed " ) ;
}
return secp256k1_ctx ;
return MP_OBJ_FROM_PTR ( o ) ;
}
STATIC void mod_trezorcrypto_secp256k1_context_delete ( void ) {
secp256k1_context_preallocated_destroy ( secp256k1_ctx ) ;
m_del ( uint8_t , secp256k1_ctx_buf , secp256k1_ctx_size ) ;
secp256k1_ctx_buf = NULL ;
secp256k1_ctx = NULL ;
/// def __del__(self):
/// """
/// Destructor.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_context___del__ ( mp_obj_t self ) {
mp_obj_secp256k1_context_t * o = MP_OBJ_TO_PTR ( self ) ;
secp256k1_context_preallocated_destroy ( o - > secp256k1_ctx ) ;
memzero ( o - > secp256k1_ctx_buf , o - > secp256k1_ctx_size ) ;
return mp_const_none ;
}
/// package: trezorcrypto.secp256k1_zkp
STATIC MP_DEFINE_CONST_FUN_OBJ_1 ( mod_trezorcrypto_secp256k1_context___del___obj ,
mod_trezorcrypto_secp256k1_context___del__ ) ;
/// def size(self):
/// """
/// Return the size in bytes of the internal secp256k1_ctx_buf buffer.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_context_size ( mp_obj_t self ) {
mp_obj_secp256k1_context_t * o = MP_OBJ_TO_PTR ( self ) ;
return mp_obj_new_int_from_uint ( o - > secp256k1_ctx_size ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1 ( mod_trezorcrypto_secp256k1_context_size_obj ,
mod_trezorcrypto_secp256k1_context_size ) ;
/// def generate_secret() -> bytes:
static const secp256k1_context * mod_trezorcrypto_get_secp256k1_context (
mp_obj_t self ) {
mp_obj_secp256k1_context_t * o = MP_OBJ_TO_PTR ( self ) ;
return o - > secp256k1_ctx ;
}
/// def generate_secret(self) -> bytes:
/// """
/// Generate secret key.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_generate_secret ( ) {
uint8_t out [ 32 ] ;
STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_generate_secret ( mp_obj_t self ) {
const secp256k1_context * ctx = mod_trezorcrypto_get_secp256k1_context ( self ) ;
uint8_t out [ 32 ] = { 0 } ;
for ( ; ; ) {
random_buffer ( out , 32 ) ;
// check whether secret > 0 && secret < curve_order
if ( 0 = = memcmp ( out ,
" \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 "
" \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 "
" \x00 \x00 \x00 \x00 \x00 \x00 " ,
32 ) )
continue ;
if ( 0 < = memcmp ( out ,
" \xFF \xFF \xFF \xFF \xFF \xFF \xFF \xFF \xFF \xFF \xFF \xFF \xFF "
" \xFF \xFF \xFE \xBA \xAE \xDC \xE6 \xAF \x48 \xA0 \x3B \xBF \xD2 "
" \x5E \x8C \xD0 \x36 \x41 \x41 " ,
32 ) )
continue ;
break ;
if ( secp256k1_ec_seckey_verify ( ctx , out ) = = 1 ) {
break ;
}
}
return mp_obj_new_bytes ( out , sizeof ( out ) ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_ 0 (
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (
mod_trezorcrypto_secp256k1_zkp_generate_secret_obj ,
mod_trezorcrypto_secp256k1_zkp_generate_secret ) ;
/// def publickey(se cret_key: bytes, compressed: bool = True) -> bytes:
/// def publickey(self, secret_key: bytes, compressed: bool = True) -> bytes:
/// """
/// Computes public key from secret key.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_publickey ( size_t n_args ,
const mp_obj_t * args ) {
const secp256k1_context * ctx = mod_trezorcrypto_secp256k1_context_create ( ) ;
STATIC mp_obj_t mod_trezorcrypto_secp256k1_context_publickey (
size_t n_args , const mp_obj_t * args ) {
const secp256k1_context * ctx =
mod_trezorcrypto_get_secp256k1_context ( args [ 0 ] ) ;
mp_buffer_info_t sk ;
mp_get_buffer_raise ( args [ 0 ] , & sk , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( args [ 1 ] , & sk , MP_BUFFER_READ ) ;
secp256k1_pubkey pk ;
if ( sk . len ! = 32 ) {
mp_raise_ValueError ( " Invalid length of secret key " ) ;
@ -118,32 +154,32 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_publickey(size_t n_args,
mp_raise_ValueError ( " Invalid secret key " ) ;
}
bool compressed = n_args < 2 | | args [ 1 ] = = mp_const_true ;
bool compressed = n_args < 3 | | args [ 2 ] = = mp_const_true ;
uint8_t out [ 65 ] ;
size_t outlen = sizeof ( out ) ;
secp256k1_ec_pubkey_serialize (
ctx , out , & outlen , & pk ,
compressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED ) ;
mod_trezorcrypto_secp256k1_context_delete ( ) ;
return mp_obj_new_bytes ( out , outlen ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (
mod_trezorcrypto_secp256k1_ zkp_publickey_obj, 1 , 2 ,
mod_trezorcrypto_secp256k1_ zkp _publickey) ;
mod_trezorcrypto_secp256k1_ context_publickey_obj, 2 , 3 ,
mod_trezorcrypto_secp256k1_ context _publickey) ;
/// def sign(
/// se cret_key: bytes, digest: bytes, compressed: bool = True
/// se lf, se cret_key: bytes, digest: bytes, compressed: bool = True
/// ) -> bytes:
/// """
/// Uses secret key to produce the signature of the digest.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_sign ( size_t n_args ,
const mp_obj_t * args ) {
const secp256k1_context * ctx = mod_trezorcrypto_secp256k1_context_create ( ) ;
STATIC mp_obj_t mod_trezorcrypto_secp256k1_context_sign ( size_t n_args ,
const mp_obj_t * args ) {
const secp256k1_context * ctx =
mod_trezorcrypto_get_secp256k1_context ( args [ 0 ] ) ;
mp_buffer_info_t sk , dig ;
mp_get_buffer_raise ( args [ 0 ] , & sk , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( args [ 1 ] , & dig , MP_BUFFER_READ ) ;
bool compressed = n_args < 3 | | args [ 2 ] = = mp_const_true ;
mp_get_buffer_raise ( args [ 1 ] , & sk , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( args [ 2 ] , & dig , MP_BUFFER_READ ) ;
bool compressed = n_args < 4 | | args [ 3 ] = = mp_const_true ;
if ( sk . len ! = 32 ) {
mp_raise_ValueError ( " Invalid length of secret key " ) ;
}
@ -159,27 +195,28 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_sign(size_t n_args,
}
secp256k1_ecdsa_recoverable_signature_serialize_compact ( ctx , & out [ 1 ] , & pby ,
& sig ) ;
mod_trezorcrypto_secp256k1_context_delete ( ) ;
out [ 0 ] = 27 + pby + compressed * 4 ;
return mp_obj_new_bytes ( out , sizeof ( out ) ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (
mod_trezorcrypto_secp256k1_ zkp_sign_obj, 2 , 3 ,
mod_trezorcrypto_secp256k1_ zkp _sign) ;
mod_trezorcrypto_secp256k1_ context_sign_obj, 3 , 4 ,
mod_trezorcrypto_secp256k1_ context _sign) ;
/// def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
/// def verify(
/// self, public_key: bytes, signature: bytes, digest: bytes
/// ) -> bool:
/// """
/// Uses public key to verify the signature of the digest.
/// Returns True on success.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_verify ( mp_obj_t public_key ,
mp_obj_t signature ,
mp_obj_t digest ) {
const secp256k1_context * ctx = mod_trezorcrypto_secp256k1_context_create ( ) ;
STATIC mp_obj_t
mod_trezorcrypto_secp256k1_context_verify ( size_t n_args , const mp_obj_t * args ) {
const secp256k1_context * ctx =
mod_trezorcrypto_get_secp256k1_context ( args [ 0 ] ) ;
mp_buffer_info_t pk , sig , dig ;
mp_get_buffer_raise ( public_key , & pk , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( signature , & sig , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( digest , & dig , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( args[ 1 ] , & pk , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( args[ 2 ] , & sig , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( args[ 3 ] , & dig , MP_BUFFER_READ ) ;
if ( pk . len ! = 33 & & pk . len ! = 65 ) {
return mp_const_false ;
}
@ -202,20 +239,20 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_verify(mp_obj_t public_key,
}
bool ret = ( 1 = = secp256k1_ecdsa_verify ( ctx , & ec_sig ,
( const uint8_t * ) dig . buf , & ec_pk ) ) ;
mod_trezorcrypto_secp256k1_context_delete ( ) ;
return mp_obj_new_bool ( ret ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3 ( mod_trezorcrypto_secp256k1_zkp_verify_obj ,
mod_trezorcrypto_secp256k1_zkp_verify ) ;
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (
mod_trezorcrypto_secp256k1_context_verify_obj , 4 , 4 ,
mod_trezorcrypto_secp256k1_context_verify ) ;
/// def verify_recover(s ignature: bytes, digest: bytes) -> bytes:
/// def verify_recover(s elf, s ignature: bytes, digest: bytes) -> bytes:
/// """
/// Uses signature of the digest to verify the digest and recover the public
/// key. Returns public key on success, None if the signature is invalid.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_ zkp _verify_recover(
mp_obj_t s ignature, mp_obj_t digest ) {
const secp256k1_context * ctx = mod_trezorcrypto_ secp256k1_context_create ( ) ;
STATIC mp_obj_t mod_trezorcrypto_secp256k1_ context _verify_recover(
mp_obj_t s elf, mp_obj_t s ignature, mp_obj_t digest ) {
const secp256k1_context * ctx = mod_trezorcrypto_ get_ secp256k1_context( self ) ;
mp_buffer_info_t sig , dig ;
mp_get_buffer_raise ( signature , & sig , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( digest , & dig , MP_BUFFER_READ ) ;
@ -246,12 +283,11 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_verify_recover(
secp256k1_ec_pubkey_serialize (
ctx , out , & pklen , & pk ,
compressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED ) ;
mod_trezorcrypto_secp256k1_context_delete ( ) ;
return mp_obj_new_bytes ( out , pklen ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_ 2 (
mod_trezorcrypto_secp256k1_ zkp _verify_recover_obj,
mod_trezorcrypto_secp256k1_ zkp _verify_recover) ;
STATIC MP_DEFINE_CONST_FUN_OBJ_ 3 (
mod_trezorcrypto_secp256k1_ context _verify_recover_obj,
mod_trezorcrypto_secp256k1_ context _verify_recover) ;
static int secp256k1_ecdh_hash_passthrough ( uint8_t * output , const uint8_t * x ,
const uint8_t * y , void * data ) {
@ -262,14 +298,14 @@ static int secp256k1_ecdh_hash_passthrough(uint8_t *output, const uint8_t *x,
return 1 ;
}
/// def multiply(se cret_key: bytes, public_key: bytes) -> bytes:
/// def multiply(se lf, se cret_key: bytes, public_key: bytes) -> bytes:
/// """
/// Multiplies point defined by public_key with scalar defined by
/// secret_key. Useful for ECDH.
/// """
STATIC mp_obj_t mod_trezorcrypto_secp256k1_ zkp_multiply( mp_obj_t secret_key ,
mp_obj_t public_key ) {
const secp256k1_context * ctx = mod_trezorcrypto_ secp256k1_context_create ( ) ;
STATIC mp_obj_t mod_trezorcrypto_secp256k1_ context_multiply(
mp_obj_t self , mp_obj_t secret_key , mp_obj_t public_key ) {
const secp256k1_context * ctx = mod_trezorcrypto_ get_ secp256k1_context( self ) ;
mp_buffer_info_t sk , pk ;
mp_get_buffer_raise ( secret_key , & sk , MP_BUFFER_READ ) ;
mp_get_buffer_raise ( public_key , & pk , MP_BUFFER_READ ) ;
@ -289,27 +325,50 @@ STATIC mp_obj_t mod_trezorcrypto_secp256k1_zkp_multiply(mp_obj_t secret_key,
secp256k1_ecdh_hash_passthrough , NULL ) ) {
mp_raise_ValueError ( " Multiply failed " ) ;
}
mod_trezorcrypto_secp256k1_context_delete ( ) ;
return mp_obj_new_bytes ( out , sizeof ( out ) ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2 ( mod_trezorcrypto_secp256k1_zkp_multiply_obj ,
mod_trezorcrypto_secp256k1_zkp_multiply ) ;
STATIC MP_DEFINE_CONST_FUN_OBJ_3 (
mod_trezorcrypto_secp256k1_context_multiply_obj ,
mod_trezorcrypto_secp256k1_context_multiply ) ;
//////////////////////////////////////////////////////////////////////////////
STATIC const mp_rom_map_elem_t
mod_trezorcrypto_secp256k1_zkp_globals_table [ ] = {
{ MP_ROM_QSTR ( MP_QSTR___name__ ) , MP_ROM_QSTR ( MP_QSTR_secp256k1_zkp ) } ,
mod_trezorcrypto_secp256k1_context_locals_dict_table [ ] = {
{ MP_ROM_QSTR ( MP_QSTR___del__ ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_context___del___obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR_size ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_context_size_obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR_generate_secret ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_zkp_generate_secret_obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR_publickey ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ zkp _publickey_obj) } ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ context _publickey_obj) } ,
{ MP_ROM_QSTR ( MP_QSTR_sign ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ zkp _sign_obj) } ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ context _sign_obj) } ,
{ MP_ROM_QSTR ( MP_QSTR_verify ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ zkp _verify_obj) } ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ context _verify_obj) } ,
{ MP_ROM_QSTR ( MP_QSTR_verify_recover ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ zkp _verify_recover_obj) } ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_ context _verify_recover_obj) } ,
{ MP_ROM_QSTR ( MP_QSTR_multiply ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_zkp_multiply_obj ) } ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_context_multiply_obj ) } ,
} ;
STATIC MP_DEFINE_CONST_DICT (
mod_trezorcrypto_secp256k1_context_locals_dict ,
mod_trezorcrypto_secp256k1_context_locals_dict_table ) ;
STATIC const mp_obj_type_t mod_trezorcrypto_secp256k1_context_type = {
{ & mp_type_type } ,
. name = MP_QSTR_Context ,
. make_new = mod_trezorcrypto_secp256k1_context_make_new ,
. locals_dict = ( void * ) & mod_trezorcrypto_secp256k1_context_locals_dict ,
} ;
STATIC const mp_rom_map_elem_t
mod_trezorcrypto_secp256k1_zkp_globals_table [ ] = {
{ MP_ROM_QSTR ( MP_QSTR___name__ ) , MP_ROM_QSTR ( MP_QSTR_secp256k1_zkp ) } ,
{ MP_ROM_QSTR ( MP_QSTR_Context ) ,
MP_ROM_PTR ( & mod_trezorcrypto_secp256k1_context_type ) } ,
} ;
STATIC MP_DEFINE_CONST_DICT ( mod_trezorcrypto_secp256k1_zkp_globals ,
mod_trezorcrypto_secp256k1_zkp_globals_table ) ;