From 26a455c0218f3e9d12cef1e6b3887b9edf799763 Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Wed, 7 Feb 2018 11:11:17 +0000 Subject: [PATCH 1/7] Add support for signing ceritificate using a Secure element Secure element communication is based on a mbed-os implementation that exposes a serial interface. --- programs/x509/cert_write.c | 410 ++++++++++++++++++++++++++++++++++++- 1 file changed, 400 insertions(+), 10 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 9cc582d61..506d1e318 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -53,10 +53,12 @@ int main( void ) #include "mbedtls/ctr_drbg.h" #include "mbedtls/md.h" #include "mbedtls/error.h" +#include "mbedtls/pk_info.h" #include #include #include +#include #if defined(MBEDTLS_X509_CSR_PARSE_C) #define USAGE_CSR \ @@ -90,6 +92,21 @@ int main( void ) #define DFL_CONSTRAINTS 1 #define DFL_DIGEST MBEDTLS_MD_SHA256 +typedef struct +{ + const char * serial_port; + unsigned char key_idx; +}remote_serial_pk_context; + +int is_remote_key( const char * remote_info ); +int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx ); +int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx ); +void mbedtls_pk_remote_free( mbedtls_pk_context * ctx ); +int serial_xfer( const char * serial_port, const unsigned char * tx_buf, + size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len, + size_t * rx_len ); +#define UNUSED(x) ((void)(x)) + #define USAGE \ "\n usage: cert_write param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -577,14 +594,23 @@ int main( int argc, char *argv[] ) mbedtls_printf( " . Loading the subject key ..." ); fflush( stdout ); - ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, - opt.subject_pwd ); - if( ret != 0 ) + if ( is_remote_key( opt.subject_key ) ) { - mbedtls_strerror( ret, buf, 1024 ); - mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile " - "returned -0x%04x - %s\n\n", -ret, buf ); - goto exit; + ret = load_pubkey_from_remote( opt.subject_key, &loaded_subject_key ); + if ( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, + opt.subject_pwd ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } } mbedtls_printf( " ok\n" ); @@ -593,8 +619,18 @@ int main( int argc, char *argv[] ) mbedtls_printf( " . Loading the issuer key ..." ); fflush( stdout ); - ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, - opt.issuer_pwd ); + if ( is_remote_key( opt.issuer_key ) ) + { + ret = setup_opaque_privkey( opt.issuer_key, &loaded_issuer_key ); + if ( ret != 0 ) + goto exit; + } + else + { + ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, + opt.issuer_pwd ); + } + if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); @@ -791,7 +827,10 @@ int main( int argc, char *argv[] ) exit: mbedtls_x509write_crt_free( &crt ); mbedtls_pk_free( &loaded_subject_key ); - mbedtls_pk_free( &loaded_issuer_key ); + if ( is_remote_key( opt.issuer_key ) ) + mbedtls_pk_remote_free( &loaded_issuer_key ); + else + mbedtls_pk_free( &loaded_issuer_key ); mbedtls_mpi_free( &serial ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); @@ -803,6 +842,357 @@ exit: return( ret ); } + +/** Below magic pattern is used with ATCAECC508A demo application (or similar) + * running on target to differentiate between user input and cert_write.exe. + */ +#define REMOTE_KEY_CMD_TAG "remote" +#define REMOTE_KEY_MAGIC_PATTERN "rEmOtEkEy" +#define REMOTE_KEY_ID_MIN 0 +#define REMOTE_KEY_ID_MAX 7 +#define REMOTE_KEY_SERIAL_BAUD CBR_9600 + +#define REMOTE_KEY_FUNC_GET_PUBKEY 0xA +#define REMOTE_KEY_FUNC_SIGN 0xB + +extern mbedtls_pk_info_t mbedtls_eckey_info; + +int is_remote_key( const char * remote_info ) +{ + size_t tag_len = strlen( REMOTE_KEY_CMD_TAG ); + printf ("is_remote_key %s\n", remote_info); + if ( strlen( remote_info ) > tag_len && + strncmp( remote_info, REMOTE_KEY_CMD_TAG, tag_len ) == 0 ) + return 1; + return 0; +} + +/** Load a transparent public key context with public key from remote device + * over serial. + * This function sends: + * rEmOtEkEy + * Receives: + * <4 bytes length indicator in network order> + */ +int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx ) +{ + int key_idx = 0, offset = 0, ret = 0; + const char * serial_port = NULL; + unsigned char func_buffer[10]; + unsigned char pub_key_buf[100]; + size_t rx_len = 0; + static mbedtls_ecp_keypair ecp_key; + + offset = strlen( REMOTE_KEY_CMD_TAG ); + key_idx = (int)remote_info[offset++]; + key_idx = key_idx - 48; // ascii to decimal + + if ( key_idx < REMOTE_KEY_ID_MIN || key_idx > REMOTE_KEY_ID_MAX ) + { + mbedtls_printf( " failed\n ! Invalid remote key index %d\n\n", key_idx ); + return( -1 ); + } + serial_port = remote_info + offset; + + /* Prepare command */ + offset = 0; + func_buffer[offset++] = REMOTE_KEY_FUNC_GET_PUBKEY; + func_buffer[offset++] = key_idx; + + if ( serial_xfer( serial_port, func_buffer, offset, pub_key_buf, sizeof( pub_key_buf ), &rx_len ) != 0 ) + { + mbedtls_printf( " failed\n ! Serial error trying to get pulic key\n\n" ); + return( -1 ); + } + + /* Import public key from received binary */ + mbedtls_ecp_keypair_init(&ecp_key); + ret = mbedtls_ecp_group_load(&ecp_key.grp, MBEDTLS_ECP_DP_SECP256R1); + if ( ret != 0 ) + return( -1 ); + ret = mbedtls_ecp_point_read_binary(&ecp_key.grp, &ecp_key.Q, pub_key_buf, rx_len ); + if ( ret != 0 ) + { + mbedtls_printf( " failed\n ! Failed to read ecp key from binary\n\n" ); + return( -1 ); + } + ctx->pk_info = &mbedtls_eckey_info; + ctx->pk_ctx = &ecp_key; + return( 0 ); +} + +/** + * @brief Tell if can do the operation given by type + * + * @param type Target type + * + * @return 0 if context can't do the operations, + * 1 otherwise. + */ +static int remote_can_do_func(const void *ctx, mbedtls_pk_type_t type) +{ + UNUSED(ctx); + /* At the moment on ECDSA is supported */ + return (MBEDTLS_PK_ECDSA == type); +} + +/** + * @brief Use STSAFE private key for signature. + * + * @param ctx ECDSA context + * @param md_alg Algorithm that was used to hash the message + * @param hash Message hash + * @param hash_len Length of hash + * @param sig Buffer that will hold the signature + * @param sig_len Length of the signature written + * @param f_rng RNG function + * @param p_rng RNG parameter + * + * @retval 0 if successful, or 1. + */ +static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + remote_serial_pk_context * remote_ctx = (remote_serial_pk_context *)ctx; + unsigned char func_buffer[1024]; + size_t offset = 0; + + UNUSED( f_rng ); + UNUSED( p_rng ); + + if ( md_alg != MBEDTLS_MD_SHA256 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + func_buffer[offset++] = REMOTE_KEY_FUNC_SIGN; + func_buffer[offset++] = remote_ctx->key_idx; + func_buffer[offset++] = hash_len >> 24; + func_buffer[offset++] = hash_len >> 16; + func_buffer[offset++] = hash_len >> 8; + func_buffer[offset++] = hash_len & 0xff; + + memcpy( func_buffer + offset, hash, hash_len ); + offset += hash_len; + + if ( serial_xfer( remote_ctx->serial_port, func_buffer, offset, sig, 100/* FIXME */, sig_len ) != 0 ) + { + mbedtls_printf( " failed\n ! Serial error in signing\n\n" ); + return( -1 ); + } + + return( 0 ); +} + +int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port, unsigned char key_idx ) +{ + // allocate remote serial context + static remote_serial_pk_context remote; + /* Opaque private key */ + static const mbedtls_pk_info_t remote_pk_info = + { + /* MBEDTLS_PK_ECKEY, */ + MBEDTLS_PK_OPAQUE, + "RemoteSerial", + NULL, + remote_can_do_func, + NULL, + NULL, + remote_sign_func, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }; + + + if ( ctx == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + remote.serial_port = serial_port; + remote.key_idx = key_idx; + ctx->pk_ctx = (void *)&remote; + ctx->pk_info = &remote_pk_info; + + return( 0 ); +} + +void mbedtls_pk_remote_free( mbedtls_pk_context * ctx ) +{ + /* Nothing to free since remote context is statically allocated. + * Within this app there is no need to scrub the memory. + */ + UNUSED( ctx ); +} + +int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx ) +{ + int key_idx = 0, offset = 0, ret = 0; + const char * serial_port = NULL; + + offset = strlen( REMOTE_KEY_CMD_TAG ); + key_idx = (int)remote_info[offset++]; + key_idx = key_idx - 48; // ascii to decimal + + if ( key_idx < REMOTE_KEY_ID_MIN || key_idx > REMOTE_KEY_ID_MAX ) + { + mbedtls_printf( " failed\n ! Invalid remote key index %d\n\n", key_idx ); + return( -1 ); + } + serial_port = remote_info + offset; + ret = mbedtls_pk_remote_setup( ctx, serial_port, key_idx ); + if ( ret != 0 ) + { + mbedtls_printf( " failed\n ! remote pk setup failure \n\n" ); + return( -1 ); + } + + return( 0 ); +} + +int serial_xfer( const char * serial_port, const unsigned char * tx_buf, + size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len, + size_t * rx_len ) +{ + char comm_name[20]; + HANDLE hComm; + DCB dcbConfig; + COMMTIMEOUTS commTimeout; + DWORD xfer_len; + unsigned char len_buf[sizeof(size_t)]; + int ret = -1; + size_t len = 0, sync_pattern_idx = 0; + + do + { + sprintf( comm_name, "\\\\.\\%s", serial_port ); + + // Open port + hComm = CreateFile( comm_name, GENERIC_READ | GENERIC_WRITE, 0, 0, + OPEN_EXISTING, 0, 0 ); + if ( hComm == INVALID_HANDLE_VALUE ) + { + mbedtls_printf( " failed\n ! failed to open port %s %lu\n\n", serial_port, GetLastError() ); + break; + } + + if( GetCommState( hComm, &dcbConfig ) ) + { + /* + dcbConfig.fBinary = TRUE; + dcbConfig.fParity = TRUE; + */ + + dcbConfig.BaudRate = REMOTE_KEY_SERIAL_BAUD; + dcbConfig.Parity = NOPARITY; + dcbConfig.ByteSize = 8; + dcbConfig.StopBits = ONESTOPBIT; + dcbConfig.fOutxCtsFlow = FALSE; // No CTS output flow control + dcbConfig.fOutxDsrFlow = FALSE; // No DSR output flow control + dcbConfig.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type + dcbConfig.fDsrSensitivity = FALSE; // DSR sensitivity + dcbConfig.fTXContinueOnXoff = TRUE; // XOFF continues Tx + dcbConfig.fOutX = FALSE; // No XON/XOFF out flow control + dcbConfig.fInX = FALSE; // No XON/XOFF in flow control + dcbConfig.fErrorChar = FALSE; // Disable error replacement + dcbConfig.fNull = FALSE; // Disable null stripping + dcbConfig.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control + dcbConfig.fAbortOnError = FALSE; // Do not abort reads/writes on error + } + else + break; + + if( !SetCommState( hComm, &dcbConfig ) ) + break; + + if( GetCommTimeouts( hComm, &commTimeout ) ) + { + commTimeout.ReadIntervalTimeout = 1000; + commTimeout.ReadTotalTimeoutMultiplier = 10; + commTimeout.ReadTotalTimeoutConstant = 1000; + commTimeout.WriteTotalTimeoutConstant = 1000; + commTimeout.WriteTotalTimeoutMultiplier = 10; + } + else + break; + + if( !SetCommTimeouts( hComm, &commTimeout ) ) + break; + + + /* Sync with peer */ + if( !WriteFile( hComm, REMOTE_KEY_MAGIC_PATTERN, strlen(REMOTE_KEY_MAGIC_PATTERN), + &xfer_len, NULL ) ) + break; + + while( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) + { + char c; + + if( !ReadFile( hComm, &c, sizeof(c), &xfer_len, NULL ) ) + break; + if ( c == REMOTE_KEY_MAGIC_PATTERN[sync_pattern_idx] ) + sync_pattern_idx++; + else + sync_pattern_idx = 0; + } + + /* Exit if there was a read error */ + if ( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) + { + printf("Failedi to sync!"); + break; + } + + { + size_t i; + printf("Tx: "); + for (i = 0; i < tx_buf_len; i++) + printf ("0x%02x ", (tx_buf)[i]); + printf("\n"); + } + if( !WriteFile( hComm, tx_buf, tx_buf_len, + &xfer_len, NULL ) ) + break; + + /* Read length indicator */ + if( !ReadFile( hComm, len_buf, sizeof(len_buf), &xfer_len, NULL ) ) + break; + + *rx_len = ( len_buf[0] << 24 ) | ( len_buf[1] << 16 ) | ( len_buf[2] << 8 ) | len_buf[3]; + if ( *rx_len > rx_buf_len ) + return( -1 ); + /* Read payload */ + while( len < *rx_len ) + { + if( !ReadFile( hComm, rx_buf + len, *rx_len - len, &xfer_len, NULL ) ) + break; + len += xfer_len; + } + printf("Received LI 0x%02x 0x%02x 0x%02x 0x%02x \n", len_buf[0], len_buf[1], len_buf[2], len_buf[3]); + { + size_t i; + printf("Rx: "); + for (i = 0; i < *rx_len; i++) + printf ("0x%02x ", (rx_buf)[i]); + printf("\n"); + } + + ret = 0; + } while( 0 ); + + if( hComm != INVALID_HANDLE_VALUE ) + { + CloseHandle( hComm ); + hComm = INVALID_HANDLE_VALUE; + } + + return( ret ); +} + #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */ From 506849b5c2a37e60ec61d9810e310528f7ecbb8e Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Sat, 17 Feb 2018 16:00:06 +0000 Subject: [PATCH 2/7] Flush serial port before sending sync pattern --- programs/x509/cert_write.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 506d1e318..94e88d483 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -1057,7 +1057,7 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len, size_t * rx_len ) { - char comm_name[20]; + char c, comm_name[20]; HANDLE hComm; DCB dcbConfig; COMMTIMEOUTS commTimeout; @@ -1081,11 +1081,6 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, if( GetCommState( hComm, &dcbConfig ) ) { - /* - dcbConfig.fBinary = TRUE; - dcbConfig.fParity = TRUE; - */ - dcbConfig.BaudRate = REMOTE_KEY_SERIAL_BAUD; dcbConfig.Parity = NOPARITY; dcbConfig.ByteSize = 8; @@ -1123,6 +1118,8 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, break; + /* Flush data on serial before sending sync pattern */ + while( ReadFile( hComm, &c, sizeof(c), &xfer_len, NULL ) && xfer_len != 0 ); /* Sync with peer */ if( !WriteFile( hComm, REMOTE_KEY_MAGIC_PATTERN, strlen(REMOTE_KEY_MAGIC_PATTERN), &xfer_len, NULL ) ) @@ -1130,8 +1127,6 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, while( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) { - char c; - if( !ReadFile( hComm, &c, sizeof(c), &xfer_len, NULL ) ) break; if ( c == REMOTE_KEY_MAGIC_PATTERN[sync_pattern_idx] ) From 7a3399019e660b54d4fdb70dc2097c95fcd3746e Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Wed, 21 Feb 2018 01:05:21 +0000 Subject: [PATCH 3/7] Minor fixes and rework --- programs/x509/cert_write.c | 810 ++++++++++++++++++++----------------- 1 file changed, 448 insertions(+), 362 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 94e88d483..0266cdadd 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -58,7 +58,9 @@ int main( void ) #include #include #include +#if defined(_WIN32) #include +#endif #if defined(MBEDTLS_X509_CSR_PARSE_C) #define USAGE_CSR \ @@ -92,19 +94,6 @@ int main( void ) #define DFL_CONSTRAINTS 1 #define DFL_DIGEST MBEDTLS_MD_SHA256 -typedef struct -{ - const char * serial_port; - unsigned char key_idx; -}remote_serial_pk_context; - -int is_remote_key( const char * remote_info ); -int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx ); -int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx ); -void mbedtls_pk_remote_free( mbedtls_pk_context * ctx ); -int serial_xfer( const char * serial_port, const unsigned char * tx_buf, - size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len, - size_t * rx_len ); #define UNUSED(x) ((void)(x)) #define USAGE \ @@ -196,6 +185,447 @@ struct options unsigned char ns_cert_type; /* NS cert type */ } opt; +#if defined(_WIN32) +/** Below are the constants used for remote Opaque key implementation. + */ + +/* Remote cryptoprocessor sync pattern. Sent to sync with the device before + * sending commands. */ +#define REMOTE_KEY_MAGIC_PATTERN "rEmOtEkEy" +#define REMOTE_KEY_CMD_TAG "//opaque_pk/ATCA" +#define REMOTE_KEY_ID_MIN 0 +#define REMOTE_KEY_ID_MAX 7 +#define REMOTE_KEY_SERIAL_BAUD CBR_9600 + +#define REMOTE_KEY_FUNC_GET_PUBKEY 0xA +#define REMOTE_KEY_FUNC_SIGN 0xB + +int is_remote_key( const char *remote_info ) +{ + size_t tag_len = strlen( REMOTE_KEY_CMD_TAG ); + if ( strlen( remote_info ) > tag_len && + strncmp( remote_info, REMOTE_KEY_CMD_TAG, tag_len ) == 0 ) + return( 1 ); + return( 0 ); +} + +int parse_remote_info( const char *remote_info, int *key_idx, const char **serial_port ) +{ + int offset = 0; + int remote_info_len = strlen( remote_info ); + + if( is_remote_key( remote_info ) == 0 ) + return( -1 ); + + offset = strlen( REMOTE_KEY_CMD_TAG ); + offset++; // Skip the delimiter. FUTURE: Add validation. + if( offset >= remote_info_len ) + return( -1 ); + *key_idx = (int) remote_info[offset++]; + offset++; // Skip the delimiter + if( offset >= remote_info_len ) + return( -1 ); + *key_idx = *key_idx - 48; // ascii to decimal + + if ( *key_idx < REMOTE_KEY_ID_MIN || *key_idx > REMOTE_KEY_ID_MAX ) + { + mbedtls_printf( " failed\n ! Invalid remote key index %d\n\n", *key_idx ); + return( -1 ); + } + *serial_port = remote_info + offset; + printf( "Got key id %d and com port %s\n", *key_idx, *serial_port ); + return( 0 ); +} + +/** + * @brief Send a command to remote cryptoprocessor and receive response. + * + * It + * - first sends a sync pattern 'rEmOtEkEy' and waits for an echo to sync + * with the remote. + * - Then it sends the tx buf supplied by the caller. + * - It waits for a 4 byte length indicator. Value 0 means error. + * - Finally it reads no. of bytes specified in received Length indicator + * and fills received data in rx_buf and returns. + * Note: success is considered when a length indicator > 0 is received and + * data size == length indicator is successfully received. + * + * + * @param serial_port Serial port to send & recv data. + * @param tx_buf Command Tx buffer + * @param tx_buf_len Tx buffer length + * @param rx_buf Out response Rx buffer + * @param rx_buf_len Rx buffer length + * @param rx_len Received data length + * + * @retval 0 if success, or -1. + */ +int serial_xfer( const char * serial_port, const unsigned char * tx_buf, + size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len, + size_t * rx_len ) +{ + char c, comm_name[20]; /* \\\\.\\COMxy = 11 characters at least */ + HANDLE h_comm; + DCB dcb_config; + COMMTIMEOUTS comm_timeout; + DWORD xfer_len; + unsigned char len_buf[sizeof(size_t)]; + int ret = -1; + size_t len = 0, sync_pattern_idx = 0; + + do + { + sprintf( comm_name, "\\\\.\\%s", serial_port ); + + h_comm = CreateFile( comm_name, GENERIC_READ | GENERIC_WRITE, 0, 0, + OPEN_EXISTING, 0, 0 ); + if ( h_comm == INVALID_HANDLE_VALUE ) + { + mbedtls_printf( " failed\n ! failed to open port %s %lu\n\n", serial_port, GetLastError() ); + break; + } + + if( GetCommState( h_comm, &dcb_config ) ) + { + dcb_config.BaudRate = REMOTE_KEY_SERIAL_BAUD; + dcb_config.Parity = NOPARITY; + dcb_config.ByteSize = 8; + dcb_config.StopBits = ONESTOPBIT; + dcb_config.fOutxCtsFlow = FALSE; // No CTS output flow control + dcb_config.fOutxDsrFlow = FALSE; // No DSR output flow control + dcb_config.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type + dcb_config.fDsrSensitivity = FALSE; // DSR sensitivity + dcb_config.fTXContinueOnXoff = TRUE; // XOFF continues Tx + dcb_config.fOutX = FALSE; // No XON/XOFF out flow control + dcb_config.fInX = FALSE; // No XON/XOFF in flow control + dcb_config.fErrorChar = FALSE; // Disable error replacement + dcb_config.fNull = FALSE; // Disable null stripping + dcb_config.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control + dcb_config.fAbortOnError = FALSE; // Do not abort reads/writes on error + } + else + { + mbedtls_printf( " failed\n ! GetCommState returned error %lu\n\n", GetLastError() ); + break; + } + + if( !SetCommState( h_comm, &dcb_config ) ) + { + mbedtls_printf( " failed\n ! SetCommState returned error %lu\n\n", GetLastError() ); + break; + } + + if( GetCommTimeouts( h_comm, &comm_timeout ) ) + { + comm_timeout.ReadIntervalTimeout = 1000; + comm_timeout.ReadTotalTimeoutMultiplier = 10; + comm_timeout.ReadTotalTimeoutConstant = 1000; + comm_timeout.WriteTotalTimeoutConstant = 1000; + comm_timeout.WriteTotalTimeoutMultiplier = 10; + } + else + { + mbedtls_printf( " failed\n ! GetCommTimeouts returned error %lu\n\n", GetLastError() ); + break; + } + + if( !SetCommTimeouts( h_comm, &comm_timeout ) ) + { + mbedtls_printf( " failed\n ! SetCommTimeouts returned error %lu\n\n", GetLastError() ); + break; + } + + + /* Flush data on serial before sending sync pattern */ + while( ReadFile( h_comm, &c, sizeof(c), &xfer_len, NULL ) && xfer_len != 0 ); + /* Sync with peer */ + if( !WriteFile( h_comm, REMOTE_KEY_MAGIC_PATTERN, strlen(REMOTE_KEY_MAGIC_PATTERN), + &xfer_len, NULL ) ) + { + mbedtls_printf( " failed\n ! WriteFile returned error %lu\n\n", GetLastError() ); + break; + } + + while( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) + { + if( !ReadFile( h_comm, &c, sizeof(c), &xfer_len, NULL ) ) + { + mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() ); + break; + } + if ( c == REMOTE_KEY_MAGIC_PATTERN[sync_pattern_idx] ) + sync_pattern_idx++; + else + sync_pattern_idx = 0; + } + + /* Exit if there was a read error */ + if ( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) + { + mbedtls_printf("Failedi to sync!\n"); + break; + } + + { + size_t i; + printf("Tx: "); + for (i = 0; i < tx_buf_len; i++) + printf ("0x%02x ", (tx_buf)[i]); + printf("\n"); + } + if( !WriteFile( h_comm, tx_buf, tx_buf_len, + &xfer_len, NULL ) ) + { + mbedtls_printf( " failed\n ! WriteFile returned error %lu\n\n", GetLastError() ); + break; + } + + /* Read LI (length indicator) */ + if( !ReadFile( h_comm, len_buf, sizeof(len_buf), &xfer_len, NULL ) ) /* Serial error */ + { + mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() ); + break; + } + + *rx_len = ( len_buf[0] << 24 ) | ( len_buf[1] << 16 ) | ( len_buf[2] << 8 ) | len_buf[3]; + if ( *rx_len == 0 ) /* LI == 0 indicates remote error */ + { + mbedtls_printf( " failed\n ! Received length indicator == 0\n\n" ); + break; + } + if ( *rx_len > rx_buf_len ) /* Buffer too small */ + { + mbedtls_printf( " failed\n ! Buffer too small to hold received data\n\n" ); + break; + } + /* Read payload */ + len = 0; + while( len < *rx_len ) + { + if( !ReadFile( h_comm, rx_buf + len, *rx_len - len, &xfer_len, NULL ) ) + { + mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() ); + break; + } + len += xfer_len; + } + if( len < *rx_len ) /* Serial error */ + { + mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() ); + break; + } + printf("Received LI 0x%02x 0x%02x 0x%02x 0x%02x \n", len_buf[0], len_buf[1], len_buf[2], len_buf[3]); + { + size_t i; + printf("Rx: "); + for (i = 0; i < *rx_len; i++) + printf ("0x%02x ", (rx_buf)[i]); + printf("\n"); + } + + ret = 0; + } while( 0 ); + + if( h_comm != INVALID_HANDLE_VALUE ) + { + CloseHandle( h_comm ); + h_comm = INVALID_HANDLE_VALUE; + } + + return( ret ); +} + +/** Load a transparent public key context with public key from remote device + * over serial. + * This function sends: + * rEmOtEkEy + * Receives: + * <4 bytes length indicator in network order> + */ +int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx ) +{ + int key_idx = 0, offset = 0, ret = 0; + const char * serial_port = NULL; + unsigned char func_buffer[10]; + unsigned char pub_key_buf[100]; + size_t rx_len = 0; + static mbedtls_ecp_keypair ecp_key; + + if( parse_remote_info( remote_info, &key_idx, &serial_port ) != 0 ) + return( -1 ); + + /* Prepare command */ + offset = 0; + func_buffer[offset++] = REMOTE_KEY_FUNC_GET_PUBKEY; + func_buffer[offset++] = key_idx; + + if( serial_xfer( serial_port, func_buffer, offset, pub_key_buf, sizeof( pub_key_buf ), &rx_len ) != 0 ) + { + mbedtls_printf( " failed\n ! Serial error trying to get pulic key\n\n" ); + return( -1 ); + } + + /* Import public key from received binary */ + mbedtls_ecp_keypair_init(&ecp_key); + ret = mbedtls_ecp_group_load(&ecp_key.grp, MBEDTLS_ECP_DP_SECP256R1); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! Failed to load ecp group\n\n" ); + return( ret ); + } + ret = mbedtls_ecp_point_read_binary(&ecp_key.grp, &ecp_key.Q, pub_key_buf, rx_len ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! Failed to read ecp key from binary\n\n" ); + return( ret ); + } + ctx->pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + ctx->pk_ctx = &ecp_key; + return( 0 ); +} + +/** + * @brief Tell if the context can do the operation given by type + * + * @param ctx PK Context + * @param type Target type + * + * @return 0 if context can't do the operations, + * 1 otherwise. + */ +static int remote_can_do_func(const void *ctx, mbedtls_pk_type_t type) +{ + UNUSED(ctx); + /* At the moment only ECDSA is supported */ + return (MBEDTLS_PK_ECDSA == type); +} + +typedef struct +{ + const char *serial_port; + unsigned char key_idx; +} remote_serial_pk_context; + +/** + * @brief Sign using remote cryptoprocessor accessed over serial. + * + * @param ctx ECDSA context + * @param md_alg Hash Algorithm that was used to hash the message. + * Only SHA256 is supported. + * @param hash Message hash + * @param hash_len Length of hash + * @param sig Buffer that will hold the signature + * @param sig_len Length of the signature written + * @param f_rng RNG function + * @param p_rng RNG parameter + * + * @retval 0 if successful, or 1. + */ +static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng) +{ + remote_serial_pk_context * remote_ctx = (remote_serial_pk_context *)ctx; + /* Required buffer = func 1 byte + key Id 1 byte + hash len 4 bytes + hash */ + unsigned char func_buffer[MBEDTLS_MD_MAX_SIZE + 4 + 1 + 1]; + size_t offset = 0; + + UNUSED( f_rng ); + UNUSED( p_rng ); + + if( md_alg != MBEDTLS_MD_SHA256 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( hash_len + 4 + 1 + 1 > sizeof( func_buffer ) ) + { + return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL ); + } + + func_buffer[offset++] = REMOTE_KEY_FUNC_SIGN; + func_buffer[offset++] = remote_ctx->key_idx; + func_buffer[offset++] = hash_len >> 24; + func_buffer[offset++] = hash_len >> 16; + func_buffer[offset++] = hash_len >> 8; + func_buffer[offset++] = hash_len; + + memcpy( func_buffer + offset, hash, hash_len ); + offset += hash_len; + + if( serial_xfer( remote_ctx->serial_port, func_buffer, offset, sig, + 100/* FIXME */, sig_len ) != 0 ) + { + mbedtls_printf( " failed\n ! Serial error in signing\n\n" ); + return( -1 ); + } + + return( 0 ); +} + +void remote_free( void *ctx ) +{ + /* Nothing to free since remote context is statically allocated. + * Within this app there is no need to scrub the memory. + */ + UNUSED( ctx ); +} + +int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port, + unsigned char key_idx ) +{ + /* allocate remote serial context */ + static remote_serial_pk_context remote; + /* Opaque private key */ + static const mbedtls_pk_info_t remote_pk_info = + { + /* MBEDTLS_PK_ECKEY, */ + MBEDTLS_PK_OPAQUE, + "RemoteSerial", + NULL, + remote_can_do_func, + NULL, + NULL, + remote_sign_func, + NULL, + NULL, + NULL, + NULL, + remote_free, + NULL + }; + + + if ( ctx == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + remote.serial_port = serial_port; + remote.key_idx = key_idx; + ctx->pk_ctx = (void *)&remote; + ctx->pk_info = &remote_pk_info; + + return( 0 ); +} + +int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx ) +{ + int key_idx = 0, ret = 0; + const char * serial_port = NULL; + + if( parse_remote_info( remote_info, &key_idx, &serial_port ) != 0 ) + return( -1 ); + + ret = mbedtls_pk_remote_setup( ctx, serial_port, key_idx ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! remote pk setup failure \n\n" ); + return( ret ); + } + + return( 0 ); +} +#endif /* _WIN32 */ + int write_certificate( mbedtls_x509write_cert *crt, const char *output_file, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) @@ -594,6 +1024,7 @@ int main( int argc, char *argv[] ) mbedtls_printf( " . Loading the subject key ..." ); fflush( stdout ); +#if defined(_WIN32) if ( is_remote_key( opt.subject_key ) ) { ret = load_pubkey_from_remote( opt.subject_key, &loaded_subject_key ); @@ -601,6 +1032,7 @@ int main( int argc, char *argv[] ) goto exit; } else +#endif { ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, opt.subject_pwd ); @@ -619,6 +1051,7 @@ int main( int argc, char *argv[] ) mbedtls_printf( " . Loading the issuer key ..." ); fflush( stdout ); +#if defined(_WIN32) if ( is_remote_key( opt.issuer_key ) ) { ret = setup_opaque_privkey( opt.issuer_key, &loaded_issuer_key ); @@ -626,6 +1059,7 @@ int main( int argc, char *argv[] ) goto exit; } else +#endif { ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, opt.issuer_pwd ); @@ -827,10 +1261,7 @@ int main( int argc, char *argv[] ) exit: mbedtls_x509write_crt_free( &crt ); mbedtls_pk_free( &loaded_subject_key ); - if ( is_remote_key( opt.issuer_key ) ) - mbedtls_pk_remote_free( &loaded_issuer_key ); - else - mbedtls_pk_free( &loaded_issuer_key ); + mbedtls_pk_free( &loaded_issuer_key ); mbedtls_mpi_free( &serial ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); @@ -843,351 +1274,6 @@ exit: return( ret ); } -/** Below magic pattern is used with ATCAECC508A demo application (or similar) - * running on target to differentiate between user input and cert_write.exe. - */ -#define REMOTE_KEY_CMD_TAG "remote" -#define REMOTE_KEY_MAGIC_PATTERN "rEmOtEkEy" -#define REMOTE_KEY_ID_MIN 0 -#define REMOTE_KEY_ID_MAX 7 -#define REMOTE_KEY_SERIAL_BAUD CBR_9600 - -#define REMOTE_KEY_FUNC_GET_PUBKEY 0xA -#define REMOTE_KEY_FUNC_SIGN 0xB - -extern mbedtls_pk_info_t mbedtls_eckey_info; - -int is_remote_key( const char * remote_info ) -{ - size_t tag_len = strlen( REMOTE_KEY_CMD_TAG ); - printf ("is_remote_key %s\n", remote_info); - if ( strlen( remote_info ) > tag_len && - strncmp( remote_info, REMOTE_KEY_CMD_TAG, tag_len ) == 0 ) - return 1; - return 0; -} - -/** Load a transparent public key context with public key from remote device - * over serial. - * This function sends: - * rEmOtEkEy - * Receives: - * <4 bytes length indicator in network order> - */ -int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx ) -{ - int key_idx = 0, offset = 0, ret = 0; - const char * serial_port = NULL; - unsigned char func_buffer[10]; - unsigned char pub_key_buf[100]; - size_t rx_len = 0; - static mbedtls_ecp_keypair ecp_key; - - offset = strlen( REMOTE_KEY_CMD_TAG ); - key_idx = (int)remote_info[offset++]; - key_idx = key_idx - 48; // ascii to decimal - - if ( key_idx < REMOTE_KEY_ID_MIN || key_idx > REMOTE_KEY_ID_MAX ) - { - mbedtls_printf( " failed\n ! Invalid remote key index %d\n\n", key_idx ); - return( -1 ); - } - serial_port = remote_info + offset; - - /* Prepare command */ - offset = 0; - func_buffer[offset++] = REMOTE_KEY_FUNC_GET_PUBKEY; - func_buffer[offset++] = key_idx; - - if ( serial_xfer( serial_port, func_buffer, offset, pub_key_buf, sizeof( pub_key_buf ), &rx_len ) != 0 ) - { - mbedtls_printf( " failed\n ! Serial error trying to get pulic key\n\n" ); - return( -1 ); - } - - /* Import public key from received binary */ - mbedtls_ecp_keypair_init(&ecp_key); - ret = mbedtls_ecp_group_load(&ecp_key.grp, MBEDTLS_ECP_DP_SECP256R1); - if ( ret != 0 ) - return( -1 ); - ret = mbedtls_ecp_point_read_binary(&ecp_key.grp, &ecp_key.Q, pub_key_buf, rx_len ); - if ( ret != 0 ) - { - mbedtls_printf( " failed\n ! Failed to read ecp key from binary\n\n" ); - return( -1 ); - } - ctx->pk_info = &mbedtls_eckey_info; - ctx->pk_ctx = &ecp_key; - return( 0 ); -} - -/** - * @brief Tell if can do the operation given by type - * - * @param type Target type - * - * @return 0 if context can't do the operations, - * 1 otherwise. - */ -static int remote_can_do_func(const void *ctx, mbedtls_pk_type_t type) -{ - UNUSED(ctx); - /* At the moment on ECDSA is supported */ - return (MBEDTLS_PK_ECDSA == type); -} - -/** - * @brief Use STSAFE private key for signature. - * - * @param ctx ECDSA context - * @param md_alg Algorithm that was used to hash the message - * @param hash Message hash - * @param hash_len Length of hash - * @param sig Buffer that will hold the signature - * @param sig_len Length of the signature written - * @param f_rng RNG function - * @param p_rng RNG parameter - * - * @retval 0 if successful, or 1. - */ -static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - remote_serial_pk_context * remote_ctx = (remote_serial_pk_context *)ctx; - unsigned char func_buffer[1024]; - size_t offset = 0; - - UNUSED( f_rng ); - UNUSED( p_rng ); - - if ( md_alg != MBEDTLS_MD_SHA256 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - func_buffer[offset++] = REMOTE_KEY_FUNC_SIGN; - func_buffer[offset++] = remote_ctx->key_idx; - func_buffer[offset++] = hash_len >> 24; - func_buffer[offset++] = hash_len >> 16; - func_buffer[offset++] = hash_len >> 8; - func_buffer[offset++] = hash_len & 0xff; - - memcpy( func_buffer + offset, hash, hash_len ); - offset += hash_len; - - if ( serial_xfer( remote_ctx->serial_port, func_buffer, offset, sig, 100/* FIXME */, sig_len ) != 0 ) - { - mbedtls_printf( " failed\n ! Serial error in signing\n\n" ); - return( -1 ); - } - - return( 0 ); -} - -int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port, unsigned char key_idx ) -{ - // allocate remote serial context - static remote_serial_pk_context remote; - /* Opaque private key */ - static const mbedtls_pk_info_t remote_pk_info = - { - /* MBEDTLS_PK_ECKEY, */ - MBEDTLS_PK_OPAQUE, - "RemoteSerial", - NULL, - remote_can_do_func, - NULL, - NULL, - remote_sign_func, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL - }; - - - if ( ctx == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - remote.serial_port = serial_port; - remote.key_idx = key_idx; - ctx->pk_ctx = (void *)&remote; - ctx->pk_info = &remote_pk_info; - - return( 0 ); -} - -void mbedtls_pk_remote_free( mbedtls_pk_context * ctx ) -{ - /* Nothing to free since remote context is statically allocated. - * Within this app there is no need to scrub the memory. - */ - UNUSED( ctx ); -} - -int setup_opaque_privkey( const char * remote_info, mbedtls_pk_context * ctx ) -{ - int key_idx = 0, offset = 0, ret = 0; - const char * serial_port = NULL; - - offset = strlen( REMOTE_KEY_CMD_TAG ); - key_idx = (int)remote_info[offset++]; - key_idx = key_idx - 48; // ascii to decimal - - if ( key_idx < REMOTE_KEY_ID_MIN || key_idx > REMOTE_KEY_ID_MAX ) - { - mbedtls_printf( " failed\n ! Invalid remote key index %d\n\n", key_idx ); - return( -1 ); - } - serial_port = remote_info + offset; - ret = mbedtls_pk_remote_setup( ctx, serial_port, key_idx ); - if ( ret != 0 ) - { - mbedtls_printf( " failed\n ! remote pk setup failure \n\n" ); - return( -1 ); - } - - return( 0 ); -} - -int serial_xfer( const char * serial_port, const unsigned char * tx_buf, - size_t tx_buf_len, unsigned char * rx_buf, size_t rx_buf_len, - size_t * rx_len ) -{ - char c, comm_name[20]; - HANDLE hComm; - DCB dcbConfig; - COMMTIMEOUTS commTimeout; - DWORD xfer_len; - unsigned char len_buf[sizeof(size_t)]; - int ret = -1; - size_t len = 0, sync_pattern_idx = 0; - - do - { - sprintf( comm_name, "\\\\.\\%s", serial_port ); - - // Open port - hComm = CreateFile( comm_name, GENERIC_READ | GENERIC_WRITE, 0, 0, - OPEN_EXISTING, 0, 0 ); - if ( hComm == INVALID_HANDLE_VALUE ) - { - mbedtls_printf( " failed\n ! failed to open port %s %lu\n\n", serial_port, GetLastError() ); - break; - } - - if( GetCommState( hComm, &dcbConfig ) ) - { - dcbConfig.BaudRate = REMOTE_KEY_SERIAL_BAUD; - dcbConfig.Parity = NOPARITY; - dcbConfig.ByteSize = 8; - dcbConfig.StopBits = ONESTOPBIT; - dcbConfig.fOutxCtsFlow = FALSE; // No CTS output flow control - dcbConfig.fOutxDsrFlow = FALSE; // No DSR output flow control - dcbConfig.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type - dcbConfig.fDsrSensitivity = FALSE; // DSR sensitivity - dcbConfig.fTXContinueOnXoff = TRUE; // XOFF continues Tx - dcbConfig.fOutX = FALSE; // No XON/XOFF out flow control - dcbConfig.fInX = FALSE; // No XON/XOFF in flow control - dcbConfig.fErrorChar = FALSE; // Disable error replacement - dcbConfig.fNull = FALSE; // Disable null stripping - dcbConfig.fRtsControl = RTS_CONTROL_DISABLE; // RTS flow control - dcbConfig.fAbortOnError = FALSE; // Do not abort reads/writes on error - } - else - break; - - if( !SetCommState( hComm, &dcbConfig ) ) - break; - - if( GetCommTimeouts( hComm, &commTimeout ) ) - { - commTimeout.ReadIntervalTimeout = 1000; - commTimeout.ReadTotalTimeoutMultiplier = 10; - commTimeout.ReadTotalTimeoutConstant = 1000; - commTimeout.WriteTotalTimeoutConstant = 1000; - commTimeout.WriteTotalTimeoutMultiplier = 10; - } - else - break; - - if( !SetCommTimeouts( hComm, &commTimeout ) ) - break; - - - /* Flush data on serial before sending sync pattern */ - while( ReadFile( hComm, &c, sizeof(c), &xfer_len, NULL ) && xfer_len != 0 ); - /* Sync with peer */ - if( !WriteFile( hComm, REMOTE_KEY_MAGIC_PATTERN, strlen(REMOTE_KEY_MAGIC_PATTERN), - &xfer_len, NULL ) ) - break; - - while( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) - { - if( !ReadFile( hComm, &c, sizeof(c), &xfer_len, NULL ) ) - break; - if ( c == REMOTE_KEY_MAGIC_PATTERN[sync_pattern_idx] ) - sync_pattern_idx++; - else - sync_pattern_idx = 0; - } - - /* Exit if there was a read error */ - if ( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) - { - printf("Failedi to sync!"); - break; - } - - { - size_t i; - printf("Tx: "); - for (i = 0; i < tx_buf_len; i++) - printf ("0x%02x ", (tx_buf)[i]); - printf("\n"); - } - if( !WriteFile( hComm, tx_buf, tx_buf_len, - &xfer_len, NULL ) ) - break; - - /* Read length indicator */ - if( !ReadFile( hComm, len_buf, sizeof(len_buf), &xfer_len, NULL ) ) - break; - - *rx_len = ( len_buf[0] << 24 ) | ( len_buf[1] << 16 ) | ( len_buf[2] << 8 ) | len_buf[3]; - if ( *rx_len > rx_buf_len ) - return( -1 ); - /* Read payload */ - while( len < *rx_len ) - { - if( !ReadFile( hComm, rx_buf + len, *rx_len - len, &xfer_len, NULL ) ) - break; - len += xfer_len; - } - printf("Received LI 0x%02x 0x%02x 0x%02x 0x%02x \n", len_buf[0], len_buf[1], len_buf[2], len_buf[3]); - { - size_t i; - printf("Rx: "); - for (i = 0; i < *rx_len; i++) - printf ("0x%02x ", (rx_buf)[i]); - printf("\n"); - } - - ret = 0; - } while( 0 ); - - if( hComm != INVALID_HANDLE_VALUE ) - { - CloseHandle( hComm ); - hComm = INVALID_HANDLE_VALUE; - } - - return( ret ); -} - #endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */ From eda800f478a914ecf27442da2e8ef764992ef995 Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Wed, 21 Feb 2018 10:39:44 +0000 Subject: [PATCH 4/7] Specify signature buffer length properly --- programs/x509/cert_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 0266cdadd..075ceb205 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -554,7 +554,7 @@ static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg, offset += hash_len; if( serial_xfer( remote_ctx->serial_port, func_buffer, offset, sig, - 100/* FIXME */, sig_len ) != 0 ) + MBEDTLS_ECDSA_MAX_SIG_LEN(256), sig_len ) != 0 ) { mbedtls_printf( " failed\n ! Serial error in signing\n\n" ); return( -1 ); From 969191f0c95207cd0ffb3e40745380eb4ba22346 Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Thu, 22 Feb 2018 11:09:40 +0000 Subject: [PATCH 5/7] Fix Windows warnings --- programs/x509/cert_write.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 075ceb205..90427a061 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -211,8 +211,8 @@ int is_remote_key( const char *remote_info ) int parse_remote_info( const char *remote_info, int *key_idx, const char **serial_port ) { - int offset = 0; - int remote_info_len = strlen( remote_info ); + size_t offset = 0; + size_t remote_info_len = strlen( remote_info ); if( is_remote_key( remote_info ) == 0 ) return( -1 ); @@ -339,7 +339,7 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, /* Flush data on serial before sending sync pattern */ while( ReadFile( h_comm, &c, sizeof(c), &xfer_len, NULL ) && xfer_len != 0 ); /* Sync with peer */ - if( !WriteFile( h_comm, REMOTE_KEY_MAGIC_PATTERN, strlen(REMOTE_KEY_MAGIC_PATTERN), + if( !WriteFile( h_comm, REMOTE_KEY_MAGIC_PATTERN, (DWORD)strlen(REMOTE_KEY_MAGIC_PATTERN), &xfer_len, NULL ) ) { mbedtls_printf( " failed\n ! WriteFile returned error %lu\n\n", GetLastError() ); @@ -362,7 +362,7 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, /* Exit if there was a read error */ if ( sync_pattern_idx != strlen(REMOTE_KEY_MAGIC_PATTERN) ) { - mbedtls_printf("Failedi to sync!\n"); + mbedtls_printf("Failed to sync!\n"); break; } @@ -373,7 +373,7 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, printf ("0x%02x ", (tx_buf)[i]); printf("\n"); } - if( !WriteFile( h_comm, tx_buf, tx_buf_len, + if( !WriteFile( h_comm, tx_buf, (DWORD)tx_buf_len, &xfer_len, NULL ) ) { mbedtls_printf( " failed\n ! WriteFile returned error %lu\n\n", GetLastError() ); @@ -402,7 +402,7 @@ int serial_xfer( const char * serial_port, const unsigned char * tx_buf, len = 0; while( len < *rx_len ) { - if( !ReadFile( h_comm, rx_buf + len, *rx_len - len, &xfer_len, NULL ) ) + if( !ReadFile( h_comm, rx_buf + len, (DWORD)(*rx_len - len), &xfer_len, NULL ) ) { mbedtls_printf( " failed\n ! ReadFile returned error %lu\n\n", GetLastError() ); break; @@ -545,10 +545,10 @@ static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg, func_buffer[offset++] = REMOTE_KEY_FUNC_SIGN; func_buffer[offset++] = remote_ctx->key_idx; - func_buffer[offset++] = hash_len >> 24; - func_buffer[offset++] = hash_len >> 16; - func_buffer[offset++] = hash_len >> 8; - func_buffer[offset++] = hash_len; + func_buffer[offset++] = (unsigned char)(hash_len >> 24); + func_buffer[offset++] = (unsigned char)(hash_len >> 16); + func_buffer[offset++] = (unsigned char)(hash_len >> 8); + func_buffer[offset++] = (unsigned char)(hash_len); memcpy( func_buffer + offset, hash, hash_len ); offset += hash_len; From 0f9708f1a6635e103963d0bad78cd9738f1f38f9 Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Thu, 22 Feb 2018 13:24:16 +0000 Subject: [PATCH 6/7] Properly use of API --- programs/x509/cert_write.c | 45 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index 90427a061..be867adcb 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -214,7 +214,7 @@ int parse_remote_info( const char *remote_info, int *key_idx, const char **seria size_t offset = 0; size_t remote_info_len = strlen( remote_info ); - if( is_remote_key( remote_info ) == 0 ) + if( !is_remote_key( remote_info ) ) return( -1 ); offset = strlen( REMOTE_KEY_CMD_TAG ); @@ -446,8 +446,8 @@ int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx { int key_idx = 0, offset = 0, ret = 0; const char * serial_port = NULL; - unsigned char func_buffer[10]; - unsigned char pub_key_buf[100]; + unsigned char func_buffer[2]; /* Op code: 1 + key Id: 1 */ + unsigned char pub_key_buf[65]; /* ECDSA Pub key: 64 + ASN.1 overhead: 1 */ size_t rx_len = 0; static mbedtls_ecp_keypair ecp_key; @@ -459,7 +459,8 @@ int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx func_buffer[offset++] = REMOTE_KEY_FUNC_GET_PUBKEY; func_buffer[offset++] = key_idx; - if( serial_xfer( serial_port, func_buffer, offset, pub_key_buf, sizeof( pub_key_buf ), &rx_len ) != 0 ) + if( serial_xfer( serial_port, func_buffer, offset, pub_key_buf, + sizeof( pub_key_buf ), &rx_len ) != 0 ) { mbedtls_printf( " failed\n ! Serial error trying to get pulic key\n\n" ); return( -1 ); @@ -479,7 +480,7 @@ int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx mbedtls_printf( " failed\n ! Failed to read ecp key from binary\n\n" ); return( ret ); } - ctx->pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + mbedtls_pk_setup( ctx, mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ); ctx->pk_ctx = &ecp_key; return( 0 ); } @@ -535,6 +536,8 @@ static int remote_sign_func(void *ctx, mbedtls_md_type_t md_alg, UNUSED( f_rng ); UNUSED( p_rng ); + /* Currently this feature only supports Crypto chip ATCAECC508A that only + * supports SHA256. */ if( md_alg != MBEDTLS_MD_SHA256 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -578,22 +581,20 @@ int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port, static remote_serial_pk_context remote; /* Opaque private key */ static const mbedtls_pk_info_t remote_pk_info = - { - /* MBEDTLS_PK_ECKEY, */ - MBEDTLS_PK_OPAQUE, - "RemoteSerial", - NULL, - remote_can_do_func, - NULL, - NULL, - remote_sign_func, - NULL, - NULL, - NULL, - NULL, - remote_free, - NULL - }; + MBEDTLS_PK_OPAQUE_INFO_1( + "RemoteSerial", + NULL, + remote_can_do_func, + NULL, + NULL, + remote_sign_func, + NULL, + NULL, + NULL, + NULL, + remote_free, + NULL + ); if ( ctx == NULL ) @@ -601,8 +602,8 @@ int mbedtls_pk_remote_setup( mbedtls_pk_context * ctx, const char * serial_port, remote.serial_port = serial_port; remote.key_idx = key_idx; + mbedtls_pk_setup( ctx, &remote_pk_info ); ctx->pk_ctx = (void *)&remote; - ctx->pk_info = &remote_pk_info; return( 0 ); } From 88953b623d2065db56bb8f700204c9302788da8b Mon Sep 17 00:00:00 2001 From: Azim Khan Date: Thu, 22 Feb 2018 17:46:48 +0000 Subject: [PATCH 7/7] Fix comment explaining ECDSA public key format --- programs/x509/cert_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c index be867adcb..2dca1a180 100644 --- a/programs/x509/cert_write.c +++ b/programs/x509/cert_write.c @@ -447,7 +447,7 @@ int load_pubkey_from_remote( const char * remote_info, mbedtls_pk_context * ctx int key_idx = 0, offset = 0, ret = 0; const char * serial_port = NULL; unsigned char func_buffer[2]; /* Op code: 1 + key Id: 1 */ - unsigned char pub_key_buf[65]; /* ECDSA Pub key: 64 + ASN.1 overhead: 1 */ + unsigned char pub_key_buf[65]; /* ECDSA Pub key: 64 + EC octet string format tag: 1 */ size_t rx_len = 0; static mbedtls_ecp_keypair ecp_key;