Skip to content

OSSL_PROVIDER_load_ex loaded but OSSL_STORE_open returs nul Context (error:1608010C:STORE routines::unsupported) #647

@hafedh-trimeche

Description

@hafedh-trimeche

Hello,

Please note that I translated from Pascal code to C one:
/* -------------------------------------------------------------------------
   Function : SSLProviderInit
   Purpose  : Loads an OpenSSL provider with optional parameters and
              performs basic validation (availability, self‑test).

   Parameters
     ctx          - Pointer to an OpenSSL library context (POSSL_LIB_CTX)
     providerName - Name of the provider to load (UTF‑8 string)
     params       - Array of provider parameters (TOSSLParams)
     activate     - Boolean flag (currently unused – the function always
                    passes "true" for the "activate" parameter)

   Returns
     Pointer to the loaded provider (POSSL_PROVIDER) or NULL on failure.
   -------------------------------------------------------------------------- */
POSSL_PROVIDER *SSLProviderInit(POSSL_LIB_CTX *ctx,
                                const char *providerName,
                                TOSSLParams params,
                                bool activate)
{
    POSSL_PROVIDER *result = NULL;
    OSSL_PARAM *sslParams = NULL;
    char *rawProviderName = NULL;
    int i, paramCount, lError;

    /* Guard against a NULL library context */
    if (ctx == NULL)
        return NULL;

    /* -----------------------------------------------------------------
       Build the parameter array expected by OSSL_PROVIDER_load_ex().
       The array consists of:
         1) A mandatory "activate" = "true" entry,
         2) One entry for each element in `params`,
         3) A terminating OSSL_PARAM construct (OSSL_PARAM_end).
       ----------------------------------------------------------------- */
    paramCount = (int)ParamsLength(params);          /* helper to obtain Length(Params) */
    sslParams = (OSSL_PARAM *)malloc(sizeof(OSSL_PARAM) * (paramCount + 2));
    if (sslParams == NULL)
        return NULL;    /* allocation failure */

    /* activate = "true" */
    sslParams[0] = OSSL_PARAM_construct_utf8_string("activate", "true", 4);

    for (i = 0; i < paramCount; ++i) {
        char *nameRaw  = UnicodeToRaw(TrimString(params[i].Name));
        char *valueRaw = UnicodeToRaw(TrimString(params[i].Value));

        /* OSSL_PARAM_construct_utf8_string expects a length without the NUL */
        sslParams[i + 1] = OSSL_PARAM_construct_utf8_string(
                               nameRaw,
                               valueRaw,
                               (size_t)strlen(valueRaw));

        /* The helper functions allocate memory; free after use */
        free(nameRaw);
        free(valueRaw);
    }

    /* Terminate the array */
    sslParams[paramCount + 1] = OSSL_PARAM_construct_end();

    /* Convert the provider name to a raw (UTF‑8) string */
    rawProviderName = UnicodeToRaw(providerName);
    if (rawProviderName == NULL) {
        free(sslParams);
        return NULL;
    }

    /* --------------------------------------------------------------
       Load the provider with the prepared parameter list.
       -------------------------------------------------------------- */
    result = OSSL_PROVIDER_load_ex(ctx, rawProviderName, sslParams);

    /* Clean up temporary conversion */
    free(rawProviderName);
    free(sslParams);

    if (result != NULL) {
        /* Verify that the provider is available in the given context */
        lError = OSSL_PROVIDER_available(ctx, rawProviderName);
        if (lError <= 0) {
            RegisterEventLog(
                SSLErrorMessage(
                    "SSLProviderInit (Not available) [%s: %s]",
                    providerName, providerName),
                LogError, LogSSL);
            SSLProviderFree(result);
            return NULL;
        }

        /* Run the provider's self‑test */
        lError = OSSL_PROVIDER_self_test(result);
        if (lError <= 0) {
            RegisterEventLog(
                SSLErrorMessage(
                    "SSLProviderInit (Self test) [%s: %s]",
                    providerName, providerName),
                LogError, LogSSL);
            SSLProviderFree(result);
            return NULL;
        }

    } else {
        /* Provider loading failed */
        RegisterEventLog(
            SSLErrorMessage(
                "SSLProviderInit (NULL) [%s: %s]",
                providerName, providerName),
            LogError, LogSSL);
    }

    return result;
}

/*=====================================================================
  Function: PKCS11_load_private_key
  Purpose : Load a private key from a PKCS#11 token using OpenSSL's
            OSSL_STORE API.
  Returns : EVP_PKEY* on success, NULL on failure.
=====================================================================*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/store.h>

/* External helper functions – assumed to exist elsewhere */
extern const char *RFC7512Encode(const char *input);
extern unsigned char *StringToRaw(const char *input);
extern void RegisterEventLog(const char *msg, int level, int facility);
extern const char *SSLErrorMessage(const char *detail);

/* Logging levels – replace with real definitions if needed */
enum { LogError = 1, LogSSL = 2 };

/*=====================================================================
  EVP_PKEY *PKCS11_load_private_key(const char *token,
                                    const char *serial,
                                    const char *label,
                                    const char *pin);
=====================================================================*/
EVP_PKEY *PKCS11_load_private_key(const char *token,
                                 const char *serial,
                                 const char *label,
                                 const char *pin)
{
    EVP_PKEY *result      = NULL;
    char *uri             = NULL;
    unsigned char *raw    = NULL;
    OSSL_STORE_CTX *ctx   = NULL;
    OSSL_STORE_INFO *info = NULL;

    /* ---------- Build the PKCS#11 URI -------------------------------- */
    const char *enc_token  = RFC7512Encode(token);
    const char *enc_serial = RFC7512Encode(serial);
    const char *enc_label  = RFC7512Encode(label);
    const char *enc_pin    = NULL;

    size_t uri_len = 0;
    uri_len = strlen("pkcs11:token=") + strlen(enc_token) +
              strlen("serial=")   + strlen(enc_serial) +
              strlen(";object=")  + strlen(enc_label) +
              strlen(";type=private") + 1;   /* nul‑terminator */

    if (pin && pin[0] != '\0') {
        enc_pin = RFC7512Encode(pin);
        uri_len += strlen("?pin-value=") + strlen(enc_pin);
    }

    uri = (char *)malloc(uri_len);
    if (!uri) {
        /* Out of memory – cannot continue */
        return NULL;
    }

    strcpy(uri, "pkcs11:token=");
    strcat(uri, enc_token);
    strcat(uri, "serial=");
    strcat(uri, enc_serial);
    strcat(uri, ";object=");
    strcat(uri, enc_label);
    strcat(uri, ";type=private");
    if (enc_pin) {
        strcat(uri, "?pin-value=");
        strcat(uri, enc_pin);
    }

    /* ---------- Convert the URI to a raw string ---------------------- */
    raw = StringToRaw(uri);
    if (!raw) {
        goto cleanup;
    }

    /* ---------- Open the store --------------------------------------- */
    ctx = OSSL_STORE_open((const char *)raw, NULL, NULL, NULL, NULL);
    if (!ctx) {
        goto cleanup;
    }

    /* Expect a private key object */
    if (OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PKEY) <= 0) {
        goto cleanup;
    }

    /* Load the first matching object */
    info = OSSL_STORE_load(ctx);
    if (!info) {
        goto cleanup;
    }

    if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) {
        result = OSSL_STORE_INFO_get1_PKEY(info);
    }
    OSSL_STORE_INFO_free(info);
    info = NULL;

cleanup:
    if (ctx) {
        OSSL_STORE_close(ctx);
    }

    if (!result) {
        char err_msg[256];
        snprintf(err_msg, sizeof(err_msg),
                 "PKCS11_load_private_key [Serial: %s  Label: %s]",
                 serial, label);
        RegisterEventLog(SSLErrorMessage(err_msg), LogError, LogSSL);
    }

    /* Free temporary buffers (StringToRaw ownership semantics are
       assumed to be handled elsewhere if needed). */
    free(uri);
    return result;
}

Setting Parameters as:
pkcs11-module-path: "D:\Developer\Resources\pkcs11\BouncyHsm\BouncyHsm.Pkcs11Lib.dll"
active: "true"
The Uri: "pkcs11:token=Bouncy;serial=750704DDBCF642CE;object=Manager;type=private?pin-value=1111"

Invoking OSSL_STORE_open, an error is generated:
PKCS11_load_private_key [Serial: 750704DDBCF642CE Label: Manager]: error:1608010C:STORE routines::unsupported

Best regards.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions