diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 7c0681549e..80a4fef32a 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -2333,6 +2333,17 @@ */ #define MBEDTLS_SHA512_C +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE_C + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +#define MBEDTLS_SSL_ASYNC_PRIVATE_C + /** * \def MBEDTLS_SSL_CACHE_C * diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 4eb7b78ebf..2fc9e46c1c 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -79,7 +79,7 @@ * ECP 4 8 (Started from top) * MD 5 4 * CIPHER 6 6 - * SSL 6 17 (Started from top) + * SSL 6 21 (Started from top) * SSL 7 31 * * Module dependent error code (5 bits 0x.00.-0x.F8.) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index e98101e19d..38538c7f1a 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -109,6 +109,7 @@ #define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6580 /**< Asynchronous operation is not completed yet */ /* * Various constants @@ -525,6 +526,160 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx, */ typedef int mbedtls_ssl_get_timer_t( void * ctx ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation + * + * Callback to start a signature operation using an + * external processor. The parameter \c cert contains + * the public key; it is up to the callback function to + * look up the associated private key or a handle to the + * private key. + * + * This function must start the signature operation. + * It is expected to be non-blocking, i.e. typically + * this function sends or enqueues a request and does + * not wait for the operation to complete. + * + * The parameters \c connection_ctx and \c cert are + * guaranteed to remain valid as long as the SSL + * configuration remains valid. On the other hand, this + * function must save the contents of \c hash, as the + * \c hash buffer is no longer valid when this function + * returns. + * + * \param connection_ctx Pointer to the connection context set in the + * SSL configuration + * \param p_operation_ctx On output, pointer to the operation context. + * This pointer will be passed later to the resume + * or detach function. The value is only used if + * an operation is started, i.e. if this callback + * returns 0 or \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS. + * \param cert Certificate containing the public key + * \param md_alg Hash algorithm + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes + * + * \return - 0 if the SSL stack should call the resume callback + * immediately. The resume function may provide the + * or may itself return + * \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS. + * - \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the SSL stack + * should return immediately without calling the resume + * callback. + * - \c MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the associated private key object instead. + * - Any other error is propagated up the call chain. + */ +typedef int mbedtls_ssl_async_sign_t( void *connection_ctx, + void **p_operation_ctx, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation + * + * Callback to start a decryption operation using an + * external processor. The parameter \c cert contains + * the public key; it is up to the callback function to + * look up the associated private key or a handle to the + * private key. + * + * This function must start the decryption operation. + * It is expected to be non-blocking, i.e. typically + * this function sends or enqueues a request and does + * not wait for the operation to complete. + * + * The parameters \c connection_ctx and \c cert are + * guaranteed to remain valid as long as the SSL + * configuration remains valid. On the other hand, this + * function must save the contents of \c hash, as the + * \c hash buffer is no longer valid when this function + * returns. + * + * \param connection_ctx Pointer to the connection context set in the + * SSL configuration + * \param p_operation_ctx On output, pointer to the operation context. + * This pointer will be passed later to the resume + * or detach function. The value is only used if + * an operation is started, i.e. if this callback + * returns 0 or \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS. + * \param cert Certificate containing the public key + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \c input buffer in bytes + * + * \return - 0 if the SSL stack should call the resume callback + * immediately. The resume function may provide the + * or may itself return + * \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS. + * - \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the SSL stack + * should return immediately without calling the resume + * callback. + * - \c MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the associated private key object instead. + * - Any other error is propagated up the call chain. + */ +typedef int mbedtls_ssl_async_decrypt_t( void *connection_ctx, + void **p_operation_ctx, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation + * + * Callback to resume an external operation + * started by the \c mbedtls_ssl_async_sign_t callback. + * + * \param connection_ctx Pointer to the connection context set in the + * SSL configuration + * \param operation_ctx Pointer to the operation context created by + * the start function. If this callback returns + * any value other than + * \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it should + * free all resources associated with this context. + * \param output Buffer containing the output on success + * \param output_len On success, number of bytes written to \c output + * \param output_size Size of the \c output buffer in bytes + * + * \return - 0 if output of the operation is available in the + * \c output buffer. + * - \c MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * - Any other error means that the operation is aborted. + * The SSL handshake is aborted. + */ +typedef int mbedtls_ssl_async_resume_t( void *connection_ctx, + void *operation_ctx, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation + * + * Callback to cancel an external operation + * started by the \c mbedtls_ssl_async_sign_t callback. + * + * \param connection_ctx Pointer to the connection context set in the + * SSL configuration + * \param operation_ctx Pointer to the operation context created by + * the start function. The callback should free + * all resources associated with this context. + */ +typedef void mbedtls_ssl_async_cancel_t( void *connection_ctx, + void *operation_ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ /* Defined below */ typedef struct mbedtls_ssl_session mbedtls_ssl_session; @@ -658,6 +813,16 @@ struct mbedtls_ssl_config mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */ + void *p_async_connection_ctx; /*!< connection context for asynchronous operation callbacks */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ + #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) const int *sig_hashes; /*!< allowed signature hashes */ #endif @@ -1291,6 +1456,40 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, void *p_export_keys ); #endif /* MBEDTLS_SSL_EXPORT_KEYS */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of \c mbedtls_ssl_async_sign_t + * for more information. This may be NULL if the + * external processor does no support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of \c mbedtls_ssl_async_decrypt_t + * for more information. This may be NULL if the + * external processor does no support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of \c mbedtls_ssl_async_resume_t + * for more information. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of \c mbedtls_ssl_async_cancel_t + * for more information. + * \param connection_ctx Pointer to the connection context which will be + * passed to the callbacks + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *connection_ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ + /** * \brief Callback type: generate a cookie * diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index f990243eea..c141e8adce 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -218,6 +218,10 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) + void *p_async_operation_ctx; /*!< asynchronous operation context */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ + #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ diff --git a/library/error.c b/library/error.c index 151ca4eae9..490a040581 100644 --- a/library/error.c +++ b/library/error.c @@ -441,6 +441,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - Asynchronous operation is not completed yet" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 9482723b3d..9626fa7a10 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6399,6 +6399,23 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, } #endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *connection_ctx ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_connection_ctx = connection_ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ + /* * SSL get accessors */ @@ -7332,6 +7349,15 @@ void mbedtls_ssl_handshake_free( const mbedtls_ssl_config *conf, } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) + if( conf->f_async_cancel != NULL && + handshake->p_async_operation_ctx != NULL ) + { + conf->f_async_cancel( conf->p_async_connection_ctx, + handshake->p_async_operation_ctx ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ + #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_free( handshake->verify_cookie ); mbedtls_free( handshake->hs_msg ); diff --git a/library/version_features.c b/library/version_features.c index 49bba11ef6..7152e702bc 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -615,6 +615,9 @@ static const char *features[] = { #if defined(MBEDTLS_SHA512_C) "MBEDTLS_SHA512_C", #endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE_C) + "MBEDTLS_SSL_ASYNC_PRIVATE_C", +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE_C */ #if defined(MBEDTLS_SSL_CACHE_C) "MBEDTLS_SSL_CACHE_C", #endif /* MBEDTLS_SSL_CACHE_C */