5353#else
5454#include "mbedtls/version.h"
5555#endif
56+ #if MICROPY_PY_SSL_ECDSA_SIGN_ALT
57+ #include "mbedtls/ecdsa.h"
58+ #include "mbedtls/asn1.h"
59+ #endif
5660
5761#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
5862
@@ -68,6 +72,9 @@ typedef struct _mp_obj_ssl_context_t {
6872 int authmode ;
6973 int * ciphersuites ;
7074 mp_obj_t handler ;
75+ #if MICROPY_PY_SSL_ECDSA_SIGN_ALT
76+ mp_obj_t ecdsa_sign_callback ;
77+ #endif
7178} mp_obj_ssl_context_t ;
7279
7380// This corresponds to an SSLSocket object.
@@ -248,6 +255,9 @@ static mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
248255 mbedtls_pk_init (& self -> pkey );
249256 self -> ciphersuites = NULL ;
250257 self -> handler = mp_const_none ;
258+ #if MICROPY_PY_SSL_ECDSA_SIGN_ALT
259+ self -> ecdsa_sign_callback = mp_const_none ;
260+ #endif
251261
252262 #ifdef MBEDTLS_DEBUG_C
253263 // Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
@@ -295,6 +305,10 @@ static void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
295305 dest [0 ] = MP_OBJ_NEW_SMALL_INT (self -> authmode );
296306 } else if (attr == MP_QSTR_verify_callback ) {
297307 dest [0 ] = self -> handler ;
308+ #if MICROPY_PY_SSL_ECDSA_SIGN_ALT
309+ } else if (attr == MP_QSTR_ecdsa_sign_callback ) {
310+ dest [0 ] = self -> ecdsa_sign_callback ;
311+ #endif
298312 } else {
299313 // Continue lookup in locals_dict.
300314 dest [1 ] = MP_OBJ_SENTINEL ;
@@ -305,6 +319,11 @@ static void ssl_context_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
305319 self -> authmode = mp_obj_get_int (dest [1 ]);
306320 dest [0 ] = MP_OBJ_NULL ;
307321 mbedtls_ssl_conf_authmode (& self -> conf , self -> authmode );
322+ #if MICROPY_PY_SSL_ECDSA_SIGN_ALT
323+ } else if (attr == MP_QSTR_ecdsa_sign_callback ) {
324+ dest [0 ] = MP_OBJ_NULL ;
325+ self -> ecdsa_sign_callback = dest [1 ];
326+ #endif
308327 } else if (attr == MP_QSTR_verify_callback ) {
309328 dest [0 ] = MP_OBJ_NULL ;
310329 self -> handler = dest [1 ];
@@ -786,6 +805,57 @@ static MP_DEFINE_CONST_OBJ_TYPE(
786805/******************************************************************************/
787806// ssl module.
788807
808+ #if MICROPY_PY_SSL_ECDSA_SIGN_ALT
809+ int micropy_mbedtls_ecdsa_sign_alt (const mbedtls_mpi * d , const unsigned char * hash , size_t hlen , unsigned char * sig , size_t sig_size , size_t * slen ) {
810+ uint8_t key [256 ];
811+
812+ // Check if the current context has an alternative sign function.
813+ mp_obj_ssl_context_t * ssl_ctx = MP_STATE_THREAD (tls_ssl_context );
814+ if (ssl_ctx == NULL || ssl_ctx -> ecdsa_sign_callback == mp_const_none ) {
815+ return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ;
816+ }
817+
818+ size_t klen = mbedtls_mpi_size (d );
819+ if (klen > sizeof (key )) {
820+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA ;
821+ }
822+
823+ // Convert the MPI private key (d) to a binary array
824+ if (mbedtls_mpi_write_binary (d , key , klen ) != 0 ) {
825+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA ;
826+ }
827+
828+ nlr_buf_t nlr ;
829+ mp_buffer_info_t sig_buf ;
830+ if (nlr_push (& nlr ) == 0 ) {
831+ mp_obj_t ret = mp_call_function_2 (ssl_ctx -> ecdsa_sign_callback ,
832+ mp_obj_new_bytearray_by_ref (klen , (void * )key ),
833+ mp_obj_new_bytearray_by_ref (hlen , (void * )hash ));
834+ if (ret == mp_const_none ) {
835+ // key couldn't be used by the alternative implementation.
836+ nlr_pop ();
837+ return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED ;
838+ }
839+ mp_get_buffer_raise (ret , & sig_buf , MP_BUFFER_READ );
840+ nlr_pop ();
841+ } else {
842+ // The alternative implementation failed to sign.
843+ mp_obj_print_exception (& mp_plat_print , MP_OBJ_FROM_PTR (nlr .ret_val ));
844+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA ;
845+ }
846+
847+ // Check if the buffer fits.
848+ if (sig_buf .len > sig_size ) {
849+ return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ;
850+ }
851+
852+ // Copy ASN.1 signature to buffer.
853+ * slen = sig_buf .len ;
854+ memcpy (sig , sig_buf .buf , sig_buf .len );
855+ return 0 ;
856+ }
857+ #endif
858+
789859static const mp_rom_map_elem_t mp_module_tls_globals_table [] = {
790860 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_tls ) },
791861
0 commit comments