From 16c6ca4995a3d7bd5a6c0cc56a1be07cd56d43d4 Mon Sep 17 00:00:00 2001 From: Anton Gerasimov Date: Mon, 3 Jun 2019 13:16:31 +0200 Subject: [PATCH] Add support for private keys in crypto devices Signed-off-by: Anton Gerasimov --- inc/azure_uhttp_c/uhttp.h | 2 + src/uhttp.c | 78 ++++++++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/inc/azure_uhttp_c/uhttp.h b/inc/azure_uhttp_c/uhttp.h index 6fe5711..eeda866 100644 --- a/inc/azure_uhttp_c/uhttp.h +++ b/inc/azure_uhttp_c/uhttp.h @@ -13,6 +13,7 @@ extern "C" { #endif /* __cplusplus */ #include "azure_c_shared_utility/httpheaders.h" +#include "azure_c_shared_utility/tlsio_cryptodev.h" #include "azure_macro_utils/macro_utils.h" #include "azure_c_shared_utility/xio.h" #include "umock_c/umock_c_prod.h" @@ -73,6 +74,7 @@ MOCKABLE_FUNCTION(, void, uhttp_client_dowork, HTTP_CLIENT_HANDLE, handle); MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_trace, HTTP_CLIENT_HANDLE, handle, bool, trace_on, bool, trace_data); MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_X509_cert, HTTP_CLIENT_HANDLE, handle, bool, ecc_type, const char*, certificate, const char*, private_key); +MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_X509_cert_cryptodev, HTTP_CLIENT_HANDLE, handle, bool, ecc_type, const char*, certificate, TLSIO_CRYPTODEV_PKEY*, private_key_cryptodev); MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_trusted_cert, HTTP_CLIENT_HANDLE, handle, const char*, certificate); MOCKABLE_FUNCTION(, const char*, uhttp_client_get_trusted_cert, HTTP_CLIENT_HANDLE, handle); MOCKABLE_FUNCTION(, HTTP_CLIENT_RESULT, uhttp_client_set_option, HTTP_CLIENT_HANDLE, handle, const char*, optionName, const void*, value); diff --git a/src/uhttp.c b/src/uhttp.c index eb88b51..03ff99d 100644 --- a/src/uhttp.c +++ b/src/uhttp.c @@ -83,6 +83,7 @@ typedef struct HTTP_CLIENT_HANDLE_DATA_TAG bool cert_type_ecc; char* x509_cert; char* x509_pk; + TLSIO_CRYPTODEV_PKEY* x509_cryptodev_pk; char* certificate; int connected; } HTTP_CLIENT_HANDLE_DATA; @@ -991,6 +992,7 @@ void uhttp_client_destroy(HTTP_CLIENT_HANDLE handle) xio_destroy(handle->xio_handle); free(handle->certificate); free(handle->x509_pk); + free(handle->x509_cryptodev_pk); free(handle->x509_cert); free(handle); } @@ -1028,9 +1030,15 @@ HTTP_CLIENT_RESULT uhttp_client_open(HTTP_CLIENT_HANDLE handle, const char* host http_data->connect_user_ctx = callback_ctx; http_data->port_num = port_num; - if (http_data->x509_cert != NULL && http_data->x509_pk != NULL) + if (http_data->x509_cert != NULL && (http_data->x509_pk != NULL || http_data->x509_cryptodev_pk != NULL)) { - if (xio_setoption(http_data->xio_handle, SU_OPTION_X509_CERT, http_data->x509_cert) != 0 || xio_setoption(http_data->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_data->x509_pk) != 0) + int rc = xio_setoption(http_data->xio_handle, SU_OPTION_X509_CERT, http_data->x509_cert); + if (http_data->x509_cryptodev_pk != NULL) { + rc |= xio_setoption(http_data->xio_handle, SU_OPTION_X509_CRYPTODEV_PRIVATE_KEY, http_data->x509_cryptodev_pk); + } else { + rc |= xio_setoption(http_data->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_data->x509_pk); + } + if (rc != 0) { LogError("Failed setting x509 certificate"); result = HTTP_CLIENT_ERROR; @@ -1356,16 +1364,10 @@ HTTP_CLIENT_RESULT uhttp_client_set_trace(HTTP_CLIENT_HANDLE handle, bool trace_ return result; } -HTTP_CLIENT_RESULT uhttp_client_set_X509_cert(HTTP_CLIENT_HANDLE handle, bool ecc_type, const char* certificate, const char* private_key) -{ - HTTP_CLIENT_RESULT result; - if (handle == NULL || certificate == NULL || private_key == NULL) - { - /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */ - result = HTTP_CLIENT_INVALID_ARG; - LogError("invalid parameter handle: %p certificate: %p private_key: %p", handle, certificate, private_key); - } - else if (handle->recv_msg.recv_state != state_initial) +static HTTP_CLIENT_RESULT uhttp_client_set_just_X509_cert(HTTP_CLIENT_HANDLE handle, bool ecc_type, const char* certificate) { + HTTP_CLIENT_RESULT result = HTTP_CLIENT_OK; + + if (handle->recv_msg.recv_state != state_initial) { result = HTTP_CLIENT_INVALID_STATE; LogError("You must set the X509 certificates before opening the connection"); @@ -1378,7 +1380,57 @@ HTTP_CLIENT_RESULT uhttp_client_set_X509_cert(HTTP_CLIENT_HANDLE handle, bool ec result = HTTP_CLIENT_ERROR; LogError("failure allocating certificate"); } - else if (mallocAndStrcpy_s(&handle->x509_pk, private_key) != 0) + } + + return result; +} + +HTTP_CLIENT_RESULT uhttp_client_set_X509_cert_cryptodev(HTTP_CLIENT_HANDLE handle, bool ecc_type, const char* certificate, TLSIO_CRYPTODEV_PKEY* private_key) +{ + HTTP_CLIENT_RESULT result; + + if (handle == NULL || certificate == NULL || private_key == NULL) + { + /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */ + result = HTTP_CLIENT_INVALID_ARG; + LogError("invalid parameter handle: %p certificate: %p private_key: %p", handle, certificate, private_key); + } + + result = uhttp_client_set_just_X509_cert(handle, ecc_type, certificate); + + if (result == HTTP_CLIENT_OK) { + handle->x509_cryptodev_pk = malloc(sizeof(TLSIO_CRYPTODEV_PKEY)); + if (handle->x509_cryptodev_pk == NULL) { + free(handle->x509_cert); + handle->x509_cert = NULL; + + result = HTTP_CLIENT_ERROR; + LogError("failure allocating private key"); + } + else + { + memcpy(handle->x509_cryptodev_pk, private_key, sizeof(TLSIO_CRYPTODEV_PKEY)); + result = HTTP_CLIENT_OK; + } + } + return result; +} + +HTTP_CLIENT_RESULT uhttp_client_set_X509_cert(HTTP_CLIENT_HANDLE handle, bool ecc_type, const char* certificate, const char* private_key) +{ + HTTP_CLIENT_RESULT result; + + if (handle == NULL || certificate == NULL || private_key == NULL) + { + /* Codes_SRS_UHTTP_07_038: [If handle is NULL then http_client_set_trace shall return HTTP_CLIENT_INVALID_ARG] */ + result = HTTP_CLIENT_INVALID_ARG; + LogError("invalid parameter handle: %p certificate: %p private_key: %p", handle, certificate, private_key); + } + + result = uhttp_client_set_just_X509_cert(handle, ecc_type, certificate); + + if (result == HTTP_CLIENT_OK) { + if (mallocAndStrcpy_s(&handle->x509_pk, private_key) != 0) { free(handle->x509_cert); handle->x509_cert = NULL;