From 48917d3bfefe584483a24b5e4ada3902d28bf3ed Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Wed, 28 Jan 2026 11:29:59 +0100 Subject: [PATCH 1/5] feat: add configuration file to provider Signed-off-by: Christian Walter --- plugins/ossl_prov/inc/azihsm_ossl_base.h | 15 +-- plugins/ossl_prov/inc/azihsm_ossl_base.h.in | 15 +-- plugins/ossl_prov/inc/azihsm_ossl_hsm.h | 25 +++- plugins/ossl_prov/src/azihsm_ossl_base.c | 140 +++++++++++++++++--- plugins/ossl_prov/src/azihsm_ossl_hsm.c | 104 +++++++++++---- 5 files changed, 230 insertions(+), 69 deletions(-) diff --git a/plugins/ossl_prov/inc/azihsm_ossl_base.h b/plugins/ossl_prov/inc/azihsm_ossl_base.h index ddb97c05..e6957ad2 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_base.h +++ b/plugins/ossl_prov/inc/azihsm_ossl_base.h @@ -15,7 +15,7 @@ extern "C" #endif // Value provided by CMake, defined in top level CMakeLists.txt -#define AZIHSM_OSSL_VERSION "" +#define AZIHSM_OSSL_VERSION "1.0.0" #define AZIHSM_OSSL_NAME "azihsm" #ifndef _Return_type_success_ @@ -37,25 +37,12 @@ typedef struct azihsm_handle priv; } AZIHSM_KEY_PAIR_OBJ; -/* Default file paths for partition keys */ -#define AZIHSM_DEFAULT_BMK_PATH "/var/lib/azihsm/bmk.bin" -#define AZIHSM_DEFAULT_MUK_PATH "/var/lib/azihsm/muk.bin" -#define AZIHSM_DEFAULT_MOBK_PATH "/var/lib/azihsm/mobk.bin" - -typedef struct -{ - char bmk_path[4096]; - char muk_path[4096]; - char mobk_path[4096]; -} AZIHSM_CONFIG; - typedef struct { OSSL_LIB_CTX *libctx; const OSSL_CORE_HANDLE *handle; azihsm_handle device; azihsm_handle session; - AZIHSM_CONFIG config; } AZIHSM_OSSL_PROV_CTX; static const OSSL_PARAM azihsm_ossl_param_types[] = { diff --git a/plugins/ossl_prov/inc/azihsm_ossl_base.h.in b/plugins/ossl_prov/inc/azihsm_ossl_base.h.in index 35d5c77e..5614fa98 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_base.h.in +++ b/plugins/ossl_prov/inc/azihsm_ossl_base.h.in @@ -15,7 +15,7 @@ extern "C" #endif // Value provided by CMake, defined in top level CMakeLists.txt -#define AZIHSM_OSSL_VERSION "@AZIHSM-OpenSSL-Provider_VERSION@" +#define AZIHSM_OSSL_VERSION "@azihsm_ossl_provider_VERSION@" #define AZIHSM_OSSL_NAME "azihsm" #ifndef _Return_type_success_ @@ -37,25 +37,12 @@ typedef struct azihsm_handle priv; } AZIHSM_KEY_PAIR_OBJ; -/* Default file paths for partition keys */ -#define AZIHSM_DEFAULT_BMK_PATH "/var/lib/azihsm/bmk.bin" -#define AZIHSM_DEFAULT_MUK_PATH "/var/lib/azihsm/muk.bin" -#define AZIHSM_DEFAULT_MOBK_PATH "/var/lib/azihsm/mobk.bin" - -typedef struct -{ - char bmk_path[4096]; - char muk_path[4096]; - char mobk_path[4096]; -} AZIHSM_CONFIG; - typedef struct { OSSL_LIB_CTX *libctx; const OSSL_CORE_HANDLE *handle; azihsm_handle device; azihsm_handle session; - AZIHSM_CONFIG config; } AZIHSM_OSSL_PROV_CTX; static const OSSL_PARAM azihsm_ossl_param_types[] = { diff --git a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h index 693c92bd..e7ba7155 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h +++ b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h @@ -10,8 +10,31 @@ extern "C" #include -#include "azihsm_ossl_base.h" +/* Default file paths for partition keys */ +#define AZIHSM_DEFAULT_BMK_PATH "/var/lib/azihsm/bmk.bin" +#define AZIHSM_DEFAULT_MUK_PATH "/var/lib/azihsm/muk.bin" +#define AZIHSM_DEFAULT_MOBK_PATH "/var/lib/azihsm/mobk.bin" +#define AZIHSM_DEFAULT_CREDENTIALS_ID_PATH "/var/lib/azihsm/credentials_id.bin" +#define AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH "/var/lib/azihsm/credentials_pin.bin" +/* Configuration parameter names for openssl.cnf */ +#define AZIHSM_CFG_CREDENTIALS_ID "azihsm-credentials-id" +#define AZIHSM_CFG_CREDENTIALS_PIN "azihsm-credentials-pin" +#define AZIHSM_CFG_BMK_PATH "azihsm-bmk-path" +#define AZIHSM_CFG_MUK_PATH "azihsm-muk-path" +#define AZIHSM_CFG_MOBK_PATH "azihsm-mobk-path" + +/* Provider configuration structure */ +typedef struct +{ + char *credentials_id_path; /* Path to credentials ID file */ + char *credentials_pin_path; /* Path to credentials PIN file */ + char *bmk_path; /* Path to BMK file */ + char *muk_path; /* Path to MUK file */ + char *mobk_path; /* Path to MOBK file */ +} AZIHSM_CONFIG; + +void azihsm_config_free(AZIHSM_CONFIG *config); void azihsm_close_device_and_session(azihsm_handle device, azihsm_handle session); azihsm_status azihsm_open_device_and_session( const AZIHSM_CONFIG *config, diff --git a/plugins/ossl_prov/src/azihsm_ossl_base.c b/plugins/ossl_prov/src/azihsm_ossl_base.c index 333dd38d..c51738e5 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_base.c +++ b/plugins/ossl_prov/src/azihsm_ossl_base.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "azihsm_ossl_base.h" @@ -297,6 +298,109 @@ static const OSSL_DISPATCH azihsm_ossl_base_dispatch[] = { { 0, NULL }, }; +/* + * Helper to strip "file:" prefix from path if present. + * Returns pointer to the actual path (may be the original string or offset by 5). + */ +static const char *strip_file_prefix(const char *path) +{ + if (path == NULL) + { + return NULL; + } + if (strncmp(path, "file:", 5) == 0) + { + return path + 5; + } + return path; +} + +/* + * Parse configuration parameters from OpenSSL config file. + * Returns a populated AZIHSM_CONFIG structure. + */ +static AZIHSM_CONFIG parse_provider_config( + const OSSL_CORE_HANDLE *handle, + OSSL_FUNC_core_get_params_fn *get_params +) +{ + AZIHSM_CONFIG config = { NULL, NULL, NULL, NULL, NULL }; + const char *credentials_id = NULL; + const char *credentials_pin = NULL; + const char *bmk_path = NULL; + const char *muk_path = NULL; + const char *mobk_path = NULL; + + OSSL_PARAM core_params[] = { + OSSL_PARAM_construct_utf8_ptr( + AZIHSM_CFG_CREDENTIALS_ID, + (char **)&credentials_id, + sizeof(void *) + ), + OSSL_PARAM_construct_utf8_ptr( + AZIHSM_CFG_CREDENTIALS_PIN, + (char **)&credentials_pin, + sizeof(void *) + ), + OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_BMK_PATH, (char **)&bmk_path, sizeof(void *)), + OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_MUK_PATH, (char **)&muk_path, sizeof(void *)), + OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_MOBK_PATH, (char **)&mobk_path, sizeof(void *)), + OSSL_PARAM_construct_end() + }; + + /* Fetch parameters from OpenSSL core (skip if no getter available) */ + if (get_params != NULL && get_params(handle, core_params) != 0) + { + /* Copy values with file: prefix handling */ + if (credentials_id != NULL) + { + const char *path = strip_file_prefix(credentials_id); + config.credentials_id_path = OPENSSL_strdup(path); + } + if (credentials_pin != NULL) + { + const char *path = strip_file_prefix(credentials_pin); + config.credentials_pin_path = OPENSSL_strdup(path); + } + if (bmk_path != NULL) + { + config.bmk_path = OPENSSL_strdup(bmk_path); + } + if (muk_path != NULL) + { + config.muk_path = OPENSSL_strdup(muk_path); + } + if (mobk_path != NULL) + { + config.mobk_path = OPENSSL_strdup(mobk_path); + } + } + + /* Apply defaults for any paths not provided in config */ + if (config.credentials_id_path == NULL) + { + config.credentials_id_path = OPENSSL_strdup(AZIHSM_DEFAULT_CREDENTIALS_ID_PATH); + } + if (config.credentials_pin_path == NULL) + { + config.credentials_pin_path = OPENSSL_strdup(AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH); + } + if (config.bmk_path == NULL) + { + config.bmk_path = OPENSSL_strdup(AZIHSM_DEFAULT_BMK_PATH); + } + if (config.muk_path == NULL) + { + config.muk_path = OPENSSL_strdup(AZIHSM_DEFAULT_MUK_PATH); + } + if (config.mobk_path == NULL) + { + config.mobk_path = OPENSSL_strdup(AZIHSM_DEFAULT_MOBK_PATH); + } + + return config; +} + OSSL_STATUS OSSL_provider_init( const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, @@ -305,7 +409,9 @@ OSSL_STATUS OSSL_provider_init( ) { AZIHSM_OSSL_PROV_CTX *ctx; + AZIHSM_CONFIG config = { NULL, NULL, NULL, NULL, NULL }; azihsm_status status; + const OSSL_DISPATCH *in_iter; if ((ctx = OPENSSL_zalloc(sizeof(AZIHSM_OSSL_PROV_CTX))) == NULL) { @@ -322,12 +428,24 @@ OSSL_STATUS OSSL_provider_init( return OSSL_FAILURE; } - /* Initialize config with hardcoded default paths */ - snprintf(ctx->config.bmk_path, sizeof(ctx->config.bmk_path), "%s", AZIHSM_DEFAULT_BMK_PATH); - snprintf(ctx->config.muk_path, sizeof(ctx->config.muk_path), "%s", AZIHSM_DEFAULT_MUK_PATH); - snprintf(ctx->config.mobk_path, sizeof(ctx->config.mobk_path), "%s", AZIHSM_DEFAULT_MOBK_PATH); + /* First pass: find core_get_params function */ + for (in_iter = in; in_iter->function_id != 0; in_iter++) + { + if (in_iter->function_id == OSSL_FUNC_CORE_GET_PARAMS) + { + core_get_params = OSSL_FUNC_core_get_params(in_iter); + break; + } + } + + /* Parse configuration from openssl.cnf */ + config = parse_provider_config(handle, core_get_params); - status = azihsm_open_device_and_session(&ctx->config, &ctx->device, &ctx->session); + /* Open device and session with configuration */ + status = azihsm_open_device_and_session(&config, &ctx->device, &ctx->session); + + /* Free configuration (no longer needed) */ + azihsm_config_free(&config); if (status != AZIHSM_STATUS_SUCCESS) { @@ -338,18 +456,6 @@ OSSL_STATUS OSSL_provider_init( return OSSL_FAILURE; } - for (; in->function_id != 0; in++) - { - - switch (in->function_id) - { - - case OSSL_FUNC_CORE_GET_PARAMS: - core_get_params = OSSL_FUNC_core_get_params(in); - break; - } - } - *provctx = ctx; *out = azihsm_ossl_base_dispatch; diff --git a/plugins/ossl_prov/src/azihsm_ossl_hsm.c b/plugins/ossl_prov/src/azihsm_ossl_hsm.c index 55eb29c1..b32378dc 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_hsm.c +++ b/plugins/ossl_prov/src/azihsm_ossl_hsm.c @@ -8,10 +8,12 @@ #include #include #include +#include #include #include #define AZIHSM_MAX_KEY_FILE_SIZE (64 * 1024) +#define AZIHSM_CREDENTIALS_SIZE 16 /* * Loads a file into an azihsm_buffer structure. @@ -196,6 +198,62 @@ static void free_buffer(struct azihsm_buffer *buffer) } } +/* + * Loads credentials from a file. + * The file must contain exactly AZIHSM_CREDENTIALS_SIZE (16) bytes. + * Returns AZIHSM_STATUS_SUCCESS on success. + */ +static azihsm_status load_credentials_from_file(const char *path, uint8_t *output) +{ + FILE *file = NULL; + size_t bytes_read = 0; + + if (path == NULL || output == NULL) + { + return AZIHSM_STATUS_INTERNAL_ERROR; + } + + file = fopen(path, "rb"); + if (file == NULL) + { + return AZIHSM_STATUS_INTERNAL_ERROR; + } + + bytes_read = fread(output, 1, AZIHSM_CREDENTIALS_SIZE, file); + fclose(file); + + if (bytes_read != AZIHSM_CREDENTIALS_SIZE) + { + OPENSSL_cleanse(output, AZIHSM_CREDENTIALS_SIZE); + return AZIHSM_STATUS_INTERNAL_ERROR; + } + + return AZIHSM_STATUS_SUCCESS; +} + +/* + * Frees the configuration structure contents. + */ +void azihsm_config_free(AZIHSM_CONFIG *config) +{ + if (config == NULL) + { + return; + } + + OPENSSL_free(config->credentials_id_path); + OPENSSL_free(config->credentials_pin_path); + OPENSSL_free(config->bmk_path); + OPENSSL_free(config->muk_path); + OPENSSL_free(config->mobk_path); + + config->credentials_id_path = NULL; + config->credentials_pin_path = NULL; + config->bmk_path = NULL; + config->muk_path = NULL; + config->mobk_path = NULL; +} + /* * picks and opens the first possible HSM device * */ @@ -274,39 +332,34 @@ azihsm_status azihsm_open_device_and_session( struct azihsm_buffer retrieved_mobk = { NULL, 0 }; struct azihsm_api_rev api_rev = { .major = 1, .minor = 0 }; + struct azihsm_credentials creds = { { 0 }, { 0 } }; - if (config == NULL) + /* Load credentials from files */ + status = load_credentials_from_file(config->credentials_id_path, creds.id); + if (status != AZIHSM_STATUS_SUCCESS) { - return AZIHSM_STATUS_INTERNAL_ERROR; + return status; } - // clang-format off - - struct azihsm_credentials creds = { - .id = - { - 0x70, 0xFC, 0xF7, 0x30, 0xB8, 0x76, 0x42, 0x38, 0xB8, 0x35, 0x80, 0x10, 0xCE, 0x8A, - 0x3F, 0x76 - }, - .pin = - { - 0xDB, 0x3D, 0xC7, 0x7F, 0xC2, 0x2E, 0x43, 0x00, 0x80, 0xD4, 0x1B, 0x31, 0xB6, 0xF0, - 0x48, 0x00 - } - }; - - // clang-format on + status = load_credentials_from_file(config->credentials_pin_path, creds.pin); + if (status != AZIHSM_STATUS_SUCCESS) + { + OPENSSL_cleanse(&creds, sizeof(creds)); + return status; + } - // Load key files if they exist + /* Load key files if they exist */ status = load_file_to_buffer(config->bmk_path, &bmk_buf); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); return status; } status = load_file_to_buffer(config->muk_path, &muk_buf); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); free_buffer(&bmk_buf); return status; } @@ -314,6 +367,7 @@ azihsm_status azihsm_open_device_and_session( status = load_file_to_buffer(config->mobk_path, &mobk_buf); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); free_buffer(&bmk_buf); free_buffer(&muk_buf); return status; @@ -322,6 +376,7 @@ azihsm_status azihsm_open_device_and_session( status = azihsm_get_device_handle(device); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); free_buffer(&bmk_buf); free_buffer(&muk_buf); free_buffer(&mobk_buf); @@ -353,24 +408,26 @@ azihsm_status azihsm_open_device_and_session( &backup_config ); - // Input buffers no longer needed after part_init + /* Input buffers no longer needed after part_init */ free_buffer(&bmk_buf); free_buffer(&muk_buf); free_buffer(&mobk_buf); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); azihsm_part_close(*device); return status; } - // Retrieve and persist BMK property + /* Retrieve and persist BMK property */ status = get_part_property(*device, AZIHSM_PART_PROP_ID_BACKUP_MASKING_KEY, &retrieved_bmk); if (status == AZIHSM_STATUS_SUCCESS && retrieved_bmk.ptr != NULL) { status = write_buffer_to_file(config->bmk_path, &retrieved_bmk); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); free_buffer(&retrieved_bmk); azihsm_part_close(*device); return status; @@ -378,7 +435,7 @@ azihsm_status azihsm_open_device_and_session( } free_buffer(&retrieved_bmk); - // Retrieve and persist MOBK property + /* Retrieve and persist MOBK property */ status = get_part_property(*device, AZIHSM_PART_PROP_ID_MASKED_OWNER_BACKUP_KEY, &retrieved_mobk); if (status == AZIHSM_STATUS_SUCCESS && retrieved_mobk.ptr != NULL) @@ -386,6 +443,7 @@ azihsm_status azihsm_open_device_and_session( status = write_buffer_to_file(config->mobk_path, &retrieved_mobk); if (status != AZIHSM_STATUS_SUCCESS) { + OPENSSL_cleanse(&creds, sizeof(creds)); free_buffer(&retrieved_mobk); azihsm_part_close(*device); return status; @@ -409,4 +467,4 @@ void azihsm_close_device_and_session(azihsm_handle device, azihsm_handle session azihsm_sess_close(session); azihsm_part_close(device); -} \ No newline at end of file +} From ad4f7423e2a3de7565df15e50205b7334cad9afd Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Fri, 6 Feb 2026 19:00:30 +0100 Subject: [PATCH 2/5] fix: Add OPENSSL_strdup Null check and improve documentation Signed-off-by: Christian Walter --- plugins/ossl_prov/inc/azihsm_ossl_base.h | 2 +- plugins/ossl_prov/src/azihsm_ossl_base.c | 49 ++++++++++++++++++------ plugins/ossl_prov/src/azihsm_ossl_hsm.c | 25 ++++++++++-- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/plugins/ossl_prov/inc/azihsm_ossl_base.h b/plugins/ossl_prov/inc/azihsm_ossl_base.h index e6957ad2..5b8f253e 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_base.h +++ b/plugins/ossl_prov/inc/azihsm_ossl_base.h @@ -15,7 +15,7 @@ extern "C" #endif // Value provided by CMake, defined in top level CMakeLists.txt -#define AZIHSM_OSSL_VERSION "1.0.0" +#define AZIHSM_OSSL_VERSION "0.0.1" #define AZIHSM_OSSL_NAME "azihsm" #ifndef _Return_type_success_ diff --git a/plugins/ossl_prov/src/azihsm_ossl_base.c b/plugins/ossl_prov/src/azihsm_ossl_base.c index c51738e5..18ecbe28 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_base.c +++ b/plugins/ossl_prov/src/azihsm_ossl_base.c @@ -315,9 +315,28 @@ static const char *strip_file_prefix(const char *path) return path; } +/* + * Validate that all required config fields are non-NULL. + * Returns 1 if valid, 0 if any required field is NULL. + */ +static int azihsm_config_is_valid(const AZIHSM_CONFIG *config) +{ + if (config == NULL) + { + return 0; + } + return config->credentials_id_path != NULL && config->credentials_pin_path != NULL && + config->bmk_path != NULL && config->muk_path != NULL && config->mobk_path != NULL; +} + /* * Parse configuration parameters from OpenSSL config file. - * Returns a populated AZIHSM_CONFIG structure. + * Returns a populated AZIHSM_CONFIG structure with all path fields set. + * + * If OPENSSL_strdup fails for any allocation, the corresponding field will be NULL. + * Caller MUST check azihsm_config_is_valid() after this call to detect allocation + * failures before using the config. On validation failure, caller should call + * azihsm_config_free() to clean up any partially allocated fields. */ static AZIHSM_CONFIG parse_provider_config( const OSSL_CORE_HANDLE *handle, @@ -348,31 +367,29 @@ static AZIHSM_CONFIG parse_provider_config( OSSL_PARAM_construct_end() }; - /* Fetch parameters from OpenSSL core (skip if no getter available) */ - if (get_params != NULL && get_params(handle, core_params) != 0) + /* Fetch parameters from OpenSSL core (returns 1 on success, 0 on failure) */ + if (get_params != NULL && get_params(handle, core_params) == 1) { - /* Copy values with file: prefix handling */ + /* Copy values with file: prefix handling for all paths */ if (credentials_id != NULL) { - const char *path = strip_file_prefix(credentials_id); - config.credentials_id_path = OPENSSL_strdup(path); + config.credentials_id_path = OPENSSL_strdup(strip_file_prefix(credentials_id)); } if (credentials_pin != NULL) { - const char *path = strip_file_prefix(credentials_pin); - config.credentials_pin_path = OPENSSL_strdup(path); + config.credentials_pin_path = OPENSSL_strdup(strip_file_prefix(credentials_pin)); } if (bmk_path != NULL) { - config.bmk_path = OPENSSL_strdup(bmk_path); + config.bmk_path = OPENSSL_strdup(strip_file_prefix(bmk_path)); } if (muk_path != NULL) { - config.muk_path = OPENSSL_strdup(muk_path); + config.muk_path = OPENSSL_strdup(strip_file_prefix(muk_path)); } if (mobk_path != NULL) { - config.mobk_path = OPENSSL_strdup(mobk_path); + config.mobk_path = OPENSSL_strdup(strip_file_prefix(mobk_path)); } } @@ -441,6 +458,16 @@ OSSL_STATUS OSSL_provider_init( /* Parse configuration from openssl.cnf */ config = parse_provider_config(handle, core_get_params); + /* Validate configuration (check for allocation failures) */ + if (!azihsm_config_is_valid(&config)) + { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + azihsm_config_free(&config); + OSSL_LIB_CTX_free(ctx->libctx); + OPENSSL_free(ctx); + return OSSL_FAILURE; + } + /* Open device and session with configuration */ status = azihsm_open_device_and_session(&config, &ctx->device, &ctx->session); diff --git a/plugins/ossl_prov/src/azihsm_ossl_hsm.c b/plugins/ossl_prov/src/azihsm_ossl_hsm.c index b32378dc..7ad80453 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_hsm.c +++ b/plugins/ossl_prov/src/azihsm_ossl_hsm.c @@ -200,13 +200,15 @@ static void free_buffer(struct azihsm_buffer *buffer) /* * Loads credentials from a file. - * The file must contain exactly AZIHSM_CREDENTIALS_SIZE (16) bytes. - * Returns AZIHSM_STATUS_SUCCESS on success. + * The file must contain exactly AZIHSM_CREDENTIALS_SIZE (16) bytes of raw binary data. + * This is the binary representation of the credential (ID or PIN), not hex-encoded. + * Returns AZIHSM_STATUS_SUCCESS on success, AZIHSM_STATUS_INTERNAL_ERROR on failure. */ static azihsm_status load_credentials_from_file(const char *path, uint8_t *output) { FILE *file = NULL; size_t bytes_read = 0; + int extra_byte; if (path == NULL || output == NULL) { @@ -220,9 +222,19 @@ static azihsm_status load_credentials_from_file(const char *path, uint8_t *outpu } bytes_read = fread(output, 1, AZIHSM_CREDENTIALS_SIZE, file); - fclose(file); if (bytes_read != AZIHSM_CREDENTIALS_SIZE) + { + fclose(file); + OPENSSL_cleanse(output, AZIHSM_CREDENTIALS_SIZE); + return AZIHSM_STATUS_INTERNAL_ERROR; + } + + /* Verify file contains exactly the expected size (no extra data) */ + extra_byte = fgetc(file); + fclose(file); + + if (extra_byte != EOF) { OPENSSL_cleanse(output, AZIHSM_CREDENTIALS_SIZE); return AZIHSM_STATUS_INTERNAL_ERROR; @@ -233,6 +245,8 @@ static azihsm_status load_credentials_from_file(const char *path, uint8_t *outpu /* * Frees the configuration structure contents. + * All pointer members are set to NULL after freeing to prevent double-free. + * Safe to call multiple times on the same config. */ void azihsm_config_free(AZIHSM_CONFIG *config) { @@ -334,6 +348,11 @@ azihsm_status azihsm_open_device_and_session( struct azihsm_api_rev api_rev = { .major = 1, .minor = 0 }; struct azihsm_credentials creds = { { 0 }, { 0 } }; + if (config == NULL || device == NULL || session == NULL) + { + return AZIHSM_STATUS_INVALID_ARGUMENT; + } + /* Load credentials from files */ status = load_credentials_from_file(config->credentials_id_path, creds.id); if (status != AZIHSM_STATUS_SUCCESS) From a844b5ba07fad4fc1f20a0fe3b13604fa82a95c8 Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Mon, 9 Feb 2026 14:18:54 +0100 Subject: [PATCH 3/5] feat(plugins/ossl_prov): add API revision configuration with version validation Add support for configuring the API revision via openssl.cnf using the 'azihsm-api-revision' parameter. Signed-off-by: Christian Walter --- plugins/ossl_prov/inc/azihsm_ossl_hsm.h | 12 ++++++ plugins/ossl_prov/src/azihsm_ossl_base.c | 54 +++++++++++++++++++++++- plugins/ossl_prov/src/azihsm_ossl_hsm.c | 6 ++- 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h index e7ba7155..d1e2aed8 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h +++ b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h @@ -9,6 +9,7 @@ extern "C" #endif #include +#include /* Default file paths for partition keys */ #define AZIHSM_DEFAULT_BMK_PATH "/var/lib/azihsm/bmk.bin" @@ -23,6 +24,15 @@ extern "C" #define AZIHSM_CFG_BMK_PATH "azihsm-bmk-path" #define AZIHSM_CFG_MUK_PATH "azihsm-muk-path" #define AZIHSM_CFG_MOBK_PATH "azihsm-mobk-path" +#define AZIHSM_CFG_API_REVISION "azihsm-api-revision" + +/* Supported API revision range */ +#define AZIHSM_API_REVISION_MIN_MAJOR 1 +#define AZIHSM_API_REVISION_MIN_MINOR 0 +#define AZIHSM_API_REVISION_MAX_MAJOR 1 +#define AZIHSM_API_REVISION_MAX_MINOR 0 +#define AZIHSM_API_REVISION_DEFAULT_MAJOR 1 +#define AZIHSM_API_REVISION_DEFAULT_MINOR 0 /* Provider configuration structure */ typedef struct @@ -32,6 +42,8 @@ typedef struct char *bmk_path; /* Path to BMK file */ char *muk_path; /* Path to MUK file */ char *mobk_path; /* Path to MOBK file */ + uint16_t api_revision_major; /* API revision major version */ + uint16_t api_revision_minor; /* API revision minor version */ } AZIHSM_CONFIG; void azihsm_config_free(AZIHSM_CONFIG *config); diff --git a/plugins/ossl_prov/src/azihsm_ossl_base.c b/plugins/ossl_prov/src/azihsm_ossl_base.c index 18ecbe28..1c131957 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_base.c +++ b/plugins/ossl_prov/src/azihsm_ossl_base.c @@ -329,6 +329,29 @@ static int azihsm_config_is_valid(const AZIHSM_CONFIG *config) config->bmk_path != NULL && config->muk_path != NULL && config->mobk_path != NULL; } +/* + * Validate that the API revision is within the supported range. + * Returns 1 if valid, 0 if out of range. + */ +static int azihsm_api_revision_is_valid(const AZIHSM_CONFIG *config) +{ + uint32_t version; + uint32_t min_version; + uint32_t max_version; + + if (config == NULL) + { + return 0; + } + + /* Combine major.minor into a single comparable value */ + version = ((uint32_t)config->api_revision_major << 16) | config->api_revision_minor; + min_version = ((uint32_t)AZIHSM_API_REVISION_MIN_MAJOR << 16) | AZIHSM_API_REVISION_MIN_MINOR; + max_version = ((uint32_t)AZIHSM_API_REVISION_MAX_MAJOR << 16) | AZIHSM_API_REVISION_MAX_MINOR; + + return version >= min_version && version <= max_version; +} + /* * Parse configuration parameters from OpenSSL config file. * Returns a populated AZIHSM_CONFIG structure with all path fields set. @@ -343,12 +366,17 @@ static AZIHSM_CONFIG parse_provider_config( OSSL_FUNC_core_get_params_fn *get_params ) { - AZIHSM_CONFIG config = { NULL, NULL, NULL, NULL, NULL }; + AZIHSM_CONFIG config = { + NULL, NULL, NULL, NULL, NULL, + AZIHSM_API_REVISION_DEFAULT_MAJOR, + AZIHSM_API_REVISION_DEFAULT_MINOR + }; const char *credentials_id = NULL; const char *credentials_pin = NULL; const char *bmk_path = NULL; const char *muk_path = NULL; const char *mobk_path = NULL; + const char *api_revision = NULL; OSSL_PARAM core_params[] = { OSSL_PARAM_construct_utf8_ptr( @@ -364,6 +392,11 @@ static AZIHSM_CONFIG parse_provider_config( OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_BMK_PATH, (char **)&bmk_path, sizeof(void *)), OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_MUK_PATH, (char **)&muk_path, sizeof(void *)), OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_MOBK_PATH, (char **)&mobk_path, sizeof(void *)), + OSSL_PARAM_construct_utf8_ptr( + AZIHSM_CFG_API_REVISION, + (char **)&api_revision, + sizeof(void *) + ), OSSL_PARAM_construct_end() }; @@ -391,6 +424,15 @@ static AZIHSM_CONFIG parse_provider_config( { config.mobk_path = OPENSSL_strdup(strip_file_prefix(mobk_path)); } + if (api_revision != NULL) + { + unsigned int major = 0, minor = 0; + if (sscanf(api_revision, "%u.%u", &major, &minor) == 2) + { + config.api_revision_major = (uint16_t)major; + config.api_revision_minor = (uint16_t)minor; + } + } } /* Apply defaults for any paths not provided in config */ @@ -468,6 +510,16 @@ OSSL_STATUS OSSL_provider_init( return OSSL_FAILURE; } + /* Validate API revision is within supported range */ + if (!azihsm_api_revision_is_valid(&config)) + { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA); + azihsm_config_free(&config); + OSSL_LIB_CTX_free(ctx->libctx); + OPENSSL_free(ctx); + return OSSL_FAILURE; + } + /* Open device and session with configuration */ status = azihsm_open_device_and_session(&config, &ctx->device, &ctx->session); diff --git a/plugins/ossl_prov/src/azihsm_ossl_hsm.c b/plugins/ossl_prov/src/azihsm_ossl_hsm.c index 7ad80453..6880d776 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_hsm.c +++ b/plugins/ossl_prov/src/azihsm_ossl_hsm.c @@ -345,7 +345,7 @@ azihsm_status azihsm_open_device_and_session( struct azihsm_buffer retrieved_bmk = { NULL, 0 }; struct azihsm_buffer retrieved_mobk = { NULL, 0 }; - struct azihsm_api_rev api_rev = { .major = 1, .minor = 0 }; + struct azihsm_api_rev api_rev = { 0 }; struct azihsm_credentials creds = { { 0 }, { 0 } }; if (config == NULL || device == NULL || session == NULL) @@ -353,6 +353,10 @@ azihsm_status azihsm_open_device_and_session( return AZIHSM_STATUS_INVALID_ARGUMENT; } + /* Use API revision from config */ + api_rev.major = config->api_revision_major; + api_rev.minor = config->api_revision_minor; + /* Load credentials from files */ status = load_credentials_from_file(config->credentials_id_path, creds.id); if (status != AZIHSM_STATUS_SUCCESS) From aa3b32768e64389273a49b3bde3bfe4da265c2cb Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Mon, 9 Feb 2026 14:21:04 +0100 Subject: [PATCH 4/5] feat(plugins/ossl_prov): support credentials paths via environment variables Add support for configuring credentials file paths via environment variables. Credentials are intentionally not configurable via openssl.cnf for security reasons. Signed-off-by: Christian Walter --- plugins/ossl_prov/inc/azihsm_ossl_hsm.h | 7 +++- plugins/ossl_prov/src/azihsm_ossl_base.c | 53 ++++++++++-------------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h index d1e2aed8..aef59ee1 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h +++ b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h @@ -11,6 +11,11 @@ extern "C" #include #include +/* Environment variable names for credentials paths. + * These are checked first, before falling back to hardcoded defaults. */ +#define AZIHSM_ENV_CREDENTIALS_ID_PATH "AZIHSM_CREDENTIALS_ID_PATH" +#define AZIHSM_ENV_CREDENTIALS_PIN_PATH "AZIHSM_CREDENTIALS_PIN_PATH" + /* Default file paths for partition keys */ #define AZIHSM_DEFAULT_BMK_PATH "/var/lib/azihsm/bmk.bin" #define AZIHSM_DEFAULT_MUK_PATH "/var/lib/azihsm/muk.bin" @@ -19,8 +24,6 @@ extern "C" #define AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH "/var/lib/azihsm/credentials_pin.bin" /* Configuration parameter names for openssl.cnf */ -#define AZIHSM_CFG_CREDENTIALS_ID "azihsm-credentials-id" -#define AZIHSM_CFG_CREDENTIALS_PIN "azihsm-credentials-pin" #define AZIHSM_CFG_BMK_PATH "azihsm-bmk-path" #define AZIHSM_CFG_MUK_PATH "azihsm-muk-path" #define AZIHSM_CFG_MOBK_PATH "azihsm-mobk-path" diff --git a/plugins/ossl_prov/src/azihsm_ossl_base.c b/plugins/ossl_prov/src/azihsm_ossl_base.c index 1c131957..52e1426c 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_base.c +++ b/plugins/ossl_prov/src/azihsm_ossl_base.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -352,6 +353,20 @@ static int azihsm_api_revision_is_valid(const AZIHSM_CONFIG *config) return version >= min_version && version <= max_version; } +/* + * Get path from environment variable, falling back to default if not set. + * Returns a newly allocated string that must be freed with OPENSSL_free. + */ +static char *get_path_from_env_or_default(const char *env_var, const char *default_path) +{ + const char *env_value = getenv(env_var); + if (env_value != NULL && env_value[0] != '\0') + { + return OPENSSL_strdup(env_value); + } + return OPENSSL_strdup(default_path); +} + /* * Parse configuration parameters from OpenSSL config file. * Returns a populated AZIHSM_CONFIG structure with all path fields set. @@ -371,24 +386,12 @@ static AZIHSM_CONFIG parse_provider_config( AZIHSM_API_REVISION_DEFAULT_MAJOR, AZIHSM_API_REVISION_DEFAULT_MINOR }; - const char *credentials_id = NULL; - const char *credentials_pin = NULL; const char *bmk_path = NULL; const char *muk_path = NULL; const char *mobk_path = NULL; const char *api_revision = NULL; OSSL_PARAM core_params[] = { - OSSL_PARAM_construct_utf8_ptr( - AZIHSM_CFG_CREDENTIALS_ID, - (char **)&credentials_id, - sizeof(void *) - ), - OSSL_PARAM_construct_utf8_ptr( - AZIHSM_CFG_CREDENTIALS_PIN, - (char **)&credentials_pin, - sizeof(void *) - ), OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_BMK_PATH, (char **)&bmk_path, sizeof(void *)), OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_MUK_PATH, (char **)&muk_path, sizeof(void *)), OSSL_PARAM_construct_utf8_ptr(AZIHSM_CFG_MOBK_PATH, (char **)&mobk_path, sizeof(void *)), @@ -403,15 +406,7 @@ static AZIHSM_CONFIG parse_provider_config( /* Fetch parameters from OpenSSL core (returns 1 on success, 0 on failure) */ if (get_params != NULL && get_params(handle, core_params) == 1) { - /* Copy values with file: prefix handling for all paths */ - if (credentials_id != NULL) - { - config.credentials_id_path = OPENSSL_strdup(strip_file_prefix(credentials_id)); - } - if (credentials_pin != NULL) - { - config.credentials_pin_path = OPENSSL_strdup(strip_file_prefix(credentials_pin)); - } + /* Copy values with file: prefix handling for key paths */ if (bmk_path != NULL) { config.bmk_path = OPENSSL_strdup(strip_file_prefix(bmk_path)); @@ -435,15 +430,13 @@ static AZIHSM_CONFIG parse_provider_config( } } - /* Apply defaults for any paths not provided in config */ - if (config.credentials_id_path == NULL) - { - config.credentials_id_path = OPENSSL_strdup(AZIHSM_DEFAULT_CREDENTIALS_ID_PATH); - } - if (config.credentials_pin_path == NULL) - { - config.credentials_pin_path = OPENSSL_strdup(AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH); - } + /* Apply defaults for any paths not provided in config. + * Credentials: environment variable > hardcoded default (not in openssl.cnf) + * Key paths: openssl.cnf > hardcoded default */ + config.credentials_id_path = get_path_from_env_or_default( + AZIHSM_ENV_CREDENTIALS_ID_PATH, AZIHSM_DEFAULT_CREDENTIALS_ID_PATH); + config.credentials_pin_path = get_path_from_env_or_default( + AZIHSM_ENV_CREDENTIALS_PIN_PATH, AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH); if (config.bmk_path == NULL) { config.bmk_path = OPENSSL_strdup(AZIHSM_DEFAULT_BMK_PATH); From d5cdeb90002ed91765c6b60c5940e3a93a83f24d Mon Sep 17 00:00:00 2001 From: Christian Walter Date: Mon, 9 Feb 2026 16:48:45 +0100 Subject: [PATCH 5/5] fix: xtask fmt issues Signed-off-by: Christian Walter --- plugins/ossl_prov/inc/azihsm_ossl_hsm.h | 10 +++++----- plugins/ossl_prov/src/azihsm_ossl_base.c | 24 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h index aef59ee1..6493e9f1 100644 --- a/plugins/ossl_prov/inc/azihsm_ossl_hsm.h +++ b/plugins/ossl_prov/inc/azihsm_ossl_hsm.h @@ -40,11 +40,11 @@ extern "C" /* Provider configuration structure */ typedef struct { - char *credentials_id_path; /* Path to credentials ID file */ - char *credentials_pin_path; /* Path to credentials PIN file */ - char *bmk_path; /* Path to BMK file */ - char *muk_path; /* Path to MUK file */ - char *mobk_path; /* Path to MOBK file */ + char *credentials_id_path; /* Path to credentials ID file */ + char *credentials_pin_path; /* Path to credentials PIN file */ + char *bmk_path; /* Path to BMK file */ + char *muk_path; /* Path to MUK file */ + char *mobk_path; /* Path to MOBK file */ uint16_t api_revision_major; /* API revision major version */ uint16_t api_revision_minor; /* API revision minor version */ } AZIHSM_CONFIG; diff --git a/plugins/ossl_prov/src/azihsm_ossl_base.c b/plugins/ossl_prov/src/azihsm_ossl_base.c index 52e1426c..f80d0b2c 100644 --- a/plugins/ossl_prov/src/azihsm_ossl_base.c +++ b/plugins/ossl_prov/src/azihsm_ossl_base.c @@ -381,11 +381,13 @@ static AZIHSM_CONFIG parse_provider_config( OSSL_FUNC_core_get_params_fn *get_params ) { - AZIHSM_CONFIG config = { - NULL, NULL, NULL, NULL, NULL, - AZIHSM_API_REVISION_DEFAULT_MAJOR, - AZIHSM_API_REVISION_DEFAULT_MINOR - }; + AZIHSM_CONFIG config = { NULL, + NULL, + NULL, + NULL, + NULL, + AZIHSM_API_REVISION_DEFAULT_MAJOR, + AZIHSM_API_REVISION_DEFAULT_MINOR }; const char *bmk_path = NULL; const char *muk_path = NULL; const char *mobk_path = NULL; @@ -434,9 +436,13 @@ static AZIHSM_CONFIG parse_provider_config( * Credentials: environment variable > hardcoded default (not in openssl.cnf) * Key paths: openssl.cnf > hardcoded default */ config.credentials_id_path = get_path_from_env_or_default( - AZIHSM_ENV_CREDENTIALS_ID_PATH, AZIHSM_DEFAULT_CREDENTIALS_ID_PATH); + AZIHSM_ENV_CREDENTIALS_ID_PATH, + AZIHSM_DEFAULT_CREDENTIALS_ID_PATH + ); config.credentials_pin_path = get_path_from_env_or_default( - AZIHSM_ENV_CREDENTIALS_PIN_PATH, AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH); + AZIHSM_ENV_CREDENTIALS_PIN_PATH, + AZIHSM_DEFAULT_CREDENTIALS_PIN_PATH + ); if (config.bmk_path == NULL) { config.bmk_path = OPENSSL_strdup(AZIHSM_DEFAULT_BMK_PATH); @@ -461,7 +467,9 @@ OSSL_STATUS OSSL_provider_init( ) { AZIHSM_OSSL_PROV_CTX *ctx; - AZIHSM_CONFIG config = { NULL, NULL, NULL, NULL, NULL }; + AZIHSM_CONFIG config = { + NULL, NULL, NULL, NULL, NULL, + }; azihsm_status status; const OSSL_DISPATCH *in_iter;