Skip to content

Add context parameter propagation to PSA Crypto driver initialization (psa_crypto_init → driver init) #347

@parmi93

Description

@parmi93

We would like to propose an enhancement to the PSA Crypto API specification regarding driver initialization.

Currently, psa_crypto_init() does not provide a standardized mechanism to pass user-defined context or configuration data down to the underlying crypto driver initialization entry points. We would like to introduce support for forwarding a generic void * argument through the PSA initialization flow, from the API entry point down to the driver-specific initialization function.

This would enable a more flexible and generic driver design, allowing a single implementation to support an entire family of devices (e.g., STSAFE-xxx) without requiring specialization at the PSA API level. The user would be able to provide a context structure containing all necessary configuration and platform-specific data, which would then be passed unchanged through the PSA framework and used by the driver for proper initialization.

The proposed behavior is that the void *arg provided to psa_crypto_init() is propagated through intermediate layers (such as driver wrappers) and ultimately received by the driver’s initialization entry point. This allows the driver to access hardware-specific handles, communication buffers, and configuration parameters in a clean and extensible way.

This change would improve modularity, portability, and scalability of PSA drivers, while keeping the API simple and backward compatible when no argument is provided.

Our goal is to have something like the following:

// Context used by STSELib porting layer to talk with the STSAFE chip
typedef struct
{
    uint8_t *tx_rx_buffer; // Buffer used by STSELib porting layer for TX/RX comms
    size_t buffer_size;
    union peripheral_t
    {
        struct i2c_t
        {
            // STM32-HAL driver I2C handle used by STSELib porting layer for I2C comms
            I2C_HandleTypeDef handle; 
            uint32_t timeout;         // Timeout for I2C communications
        } i2c;
        struct one_wire_t
        {
            // STM32-HAL driver 1-wire handle used by STSELib porting layer for 1-wire comms
            OneWrite_HandleTypeDef handle; 
        } one_wire;
    } peripheral;
} comm_t;

typedef struct 
{
    stse_Handler_t stse_handle; // STSELib driver handle
    comm_t comm;  // Used by STSELib porting layer to talk with the STSAFE chip
} stsafe_psa_handle_t;

void main()
{
    stsafe_psa_handle_t stsafe_psa_handle = {
        .stse_handle = {
            .device_type = STSAFE_A110, // Or STSAFE_A100, STSAFE_A120, etc.
            .io.busID    = 0,
            .io.BusType  = STSE_BUS_TYPE_I2C, // Or STSE_BUS_TYPE_ST1WIRE for 1-Wire protocol
        },
        .comm = {
            .tx_rx_buffer = malloc(STSAFEA_MAXIMUM_CMD_RSP_LENGTH_A110 + 3),
            .buffer_size  = STSAFEA_MAXIMUM_CMD_RSP_LENGTH_A110 + 3,
            .peripheral = {
                .i2c = {
                    .handle = {
                        .Instance = I2C3, // I2C peripheral 3
                        .Init = {
                            .Timing          = 0x00702991,
                            .AddressingMode  = I2C_ADDRESSINGMODE_7BIT,
                            .DualAddressMode = I2C_DUALADDRESS_DISABLE,
                            .NoStretchMode   = I2C_NOSTRETCH_DISABLE,
                        },
                    },
                    .timeout = 1000,
                },
            },
        },
    };

    psa_crypto_init((void *)&stsafe_psa_handle);
}

What we would like is for the void *arg of psa_crypto_init() to be passed all the way down to the init entry point (stsafe_psa_opaque_init()), as illustrated in the following call tree:

psa_crypto_init(void *arg)
└─> psa_driver_wrapper_init(void *arg) // Driver wrapper (autogenerated based on JSON driver manifest)
    └─> stsafe_psa_opaque_init(void *arg) // User-defined PSA init entry point
        └─> stse_init(stse_handle *stse, void *arg) // Initialize the STSELib driver
            └─> stse_platform_i2c_init(void *arg) // User-defined STSELib porting layer
                └─> HAL_I2C_Init(I2C_HandleTypeDef *hi2c) // Initialize the STM32-HAL I2C driver

This way, the entry point can be defined in a more generic way, supporting a family of chips (STSAFE-xxx) instead of being specialized for a specific chip, as shown in the following example:

psa_status_t stsafe_psa_opaque_init(void *arg)
{
    stsafe_psa_handle_t *stse_psa_handle = (stsafe_psa_handle_t *)arg;
    
    // Power on the STSAFE-xxx chip
    if (stse_device_power_on(&(stse_psa_handle->stse_handle)) == STSE_OK)
    {
        // Init the STSAFE-xxx chip
        if (stse_init(&(stse_psa_handle->stse_handle), (void *)&(stse_psa_handle->comm)) == STSE_OK)
        {
            return PSA_SUCCESS;
        }
    }
    
    return PSA_ERROR_GENERIC_ERROR;
}

In this way, the driver can be initialized by the user by calling psa_crypto_init() with a void pointer that is forwarded as-is directly to the PSA driver, which can then use this parameter to perform a targeted initialization.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions