/*
 *  PSA crypto support for secure element drivers
 */
/*
 *  Copyright The Mbed TLS Contributors
 *  SPDX-License-Identifier: Apache-2.0
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
 *  not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include "common.h"

#if defined(MBEDTLS_PSA_CRYPTO_SE_C)

#include <assert.h>
#include <stdint.h>
#include <string.h>

#include "psa/crypto_se_driver.h"

#include "psa_crypto_se.h"

#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include "psa_crypto_its.h"
#else /* Native ITS implementation */
#include "psa/error.h"
#include "psa/internal_trusted_storage.h"
#endif

#include "mbedtls/platform.h"



/****************************************************************/
/* Driver lookup */
/****************************************************************/

/* This structure is identical to psa_drv_se_context_t declared in
 * `crypto_se_driver.h`, except that some parts are writable here
 * (non-const, or pointer to non-const). */
typedef struct
{
    void *persistent_data;
    size_t persistent_data_size;
    uintptr_t transient_data;
} psa_drv_se_internal_context_t;

struct psa_se_drv_table_entry_s
{
    psa_key_location_t location;
    const psa_drv_se_t *methods;
    union
    {
        psa_drv_se_internal_context_t internal;
        psa_drv_se_context_t context;
    } u;
};

static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];

psa_se_drv_table_entry_t *psa_get_se_driver_entry(
    psa_key_lifetime_t lifetime )
{
    size_t i;
    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
    /* In the driver table, location=0 means an entry that isn't used.
     * No driver has a location of 0 because it's a reserved value
     * (which designates transparent keys). Make sure we never return
     * a driver entry for location 0. */
    if( location == 0 )
        return( NULL );
    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
    {
        if( driver_table[i].location == location )
            return( &driver_table[i] );
    }
    return( NULL );
}

const psa_drv_se_t *psa_get_se_driver_methods(
    const psa_se_drv_table_entry_t *driver )
{
    return( driver->methods );
}

psa_drv_se_context_t *psa_get_se_driver_context(
    psa_se_drv_table_entry_t *driver )
{
    return( &driver->u.context );
}

int psa_get_se_driver( psa_key_lifetime_t lifetime,
                       const psa_drv_se_t **p_methods,
                       psa_drv_se_context_t **p_drv_context)
{
    psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime );
    if( p_methods != NULL )
        *p_methods = ( driver ? driver->methods : NULL );
    if( p_drv_context != NULL )
        *p_drv_context = ( driver ? &driver->u.context : NULL );
    return( driver != NULL );
}



/****************************************************************/
/* Persistent data management */
/****************************************************************/

static psa_status_t psa_get_se_driver_its_file_uid(
    const psa_se_drv_table_entry_t *driver,
    psa_storage_uid_t *uid )
{
    if( driver->location > PSA_MAX_SE_LOCATION )
        return( PSA_ERROR_NOT_SUPPORTED );

#if SIZE_MAX > UINT32_MAX
    /* ITS file sizes are limited to 32 bits. */
    if( driver->u.internal.persistent_data_size > UINT32_MAX )
        return( PSA_ERROR_NOT_SUPPORTED );
#endif

    /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
    *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;
    return( PSA_SUCCESS );
}

psa_status_t psa_load_se_persistent_data(
    const psa_se_drv_table_entry_t *driver )
{
    psa_status_t status;
    psa_storage_uid_t uid;
    size_t length;

    status = psa_get_se_driver_its_file_uid( driver, &uid );
    if( status != PSA_SUCCESS )
        return( status );

    /* Read the amount of persistent data that the driver requests.
     * If the data in storage is larger, it is truncated. If the data
     * in storage is smaller, silently keep what is already at the end
     * of the output buffer. */
    /* psa_get_se_driver_its_file_uid ensures that the size_t
     * persistent_data_size is in range, but compilers don't know that,
     * so cast to reassure them. */
    return( psa_its_get( uid, 0,
                         (uint32_t) driver->u.internal.persistent_data_size,
                         driver->u.internal.persistent_data,
                         &length ) );
}

psa_status_t psa_save_se_persistent_data(
    const psa_se_drv_table_entry_t *driver )
{
    psa_status_t status;
    psa_storage_uid_t uid;

    status = psa_get_se_driver_its_file_uid( driver, &uid );
    if( status != PSA_SUCCESS )
        return( status );

    /* psa_get_se_driver_its_file_uid ensures that the size_t
     * persistent_data_size is in range, but compilers don't know that,
     * so cast to reassure them. */
    return( psa_its_set( uid,
                         (uint32_t) driver->u.internal.persistent_data_size,
                         driver->u.internal.persistent_data,
                         0 ) );
}

psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location )
{
    psa_storage_uid_t uid;
    if( location > PSA_MAX_SE_LOCATION )
        return( PSA_ERROR_NOT_SUPPORTED );
    uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;
    return( psa_its_remove( uid ) );
}

psa_status_t psa_find_se_slot_for_key(
    const psa_key_attributes_t *attributes,
    psa_key_creation_method_t method,
    psa_se_drv_table_entry_t *driver,
    psa_key_slot_number_t *slot_number )
{
    psa_status_t status;
    psa_key_location_t key_location =
        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) );

    /* If the location is wrong, it's a bug in the library. */
    if( driver->location != key_location )
        return( PSA_ERROR_CORRUPTION_DETECTED );

    /* If the driver doesn't support key creation in any way, give up now. */
    if( driver->methods->key_management == NULL )
        return( PSA_ERROR_NOT_SUPPORTED );

    if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS )
    {
        /* The application wants to use a specific slot. Allow it if
         * the driver supports it. On a system with isolation,
         * the crypto service must check that the application is
         * permitted to request this slot. */
        psa_drv_se_validate_slot_number_t p_validate_slot_number =
            driver->methods->key_management->p_validate_slot_number;
        if( p_validate_slot_number == NULL )
            return( PSA_ERROR_NOT_SUPPORTED );
        status = p_validate_slot_number( &driver->u.context,
                                         driver->u.internal.persistent_data,
                                         attributes, method,
                                         *slot_number );
    }
    else if( method == PSA_KEY_CREATION_REGISTER )
    {
        /* The application didn't specify a slot number. This doesn't
         * make sense when registering a slot. */
        return( PSA_ERROR_INVALID_ARGUMENT );
    }
    else
    {
        /* The application didn't tell us which slot to use. Let the driver
         * choose. This is the normal case. */
        psa_drv_se_allocate_key_t p_allocate =
            driver->methods->key_management->p_allocate;
        if( p_allocate == NULL )
            return( PSA_ERROR_NOT_SUPPORTED );
        status = p_allocate( &driver->u.context,
                             driver->u.internal.persistent_data,
                             attributes, method,
                             slot_number );
    }
    return( status );
}

psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver,
                                 psa_key_slot_number_t slot_number )
{
    psa_status_t status;
    psa_status_t storage_status;
    /* Normally a missing method would mean that the action is not
     * supported. But psa_destroy_key() is not supposed to return
     * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should
     * be able to destroy it. The only use case for a driver that
     * does not have a way to destroy keys at all is if the keys are
     * locked in a read-only state: we can use the keys but not
     * destroy them. Hence, if the driver doesn't support destroying
     * keys, it's really a lack of permission. */
    if( driver->methods->key_management == NULL ||
        driver->methods->key_management->p_destroy == NULL )
        return( PSA_ERROR_NOT_PERMITTED );
    status = driver->methods->key_management->p_destroy(
        &driver->u.context,
        driver->u.internal.persistent_data,
        slot_number );
    storage_status = psa_save_se_persistent_data( driver );
    return( status == PSA_SUCCESS ? storage_status : status );
}

psa_status_t psa_init_all_se_drivers( void )
{
    size_t i;
    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
    {
        psa_se_drv_table_entry_t *driver = &driver_table[i];
        if( driver->location == 0 )
            continue; /* skipping unused entry */
        const psa_drv_se_t *methods = psa_get_se_driver_methods( driver );
        if( methods->p_init != NULL )
        {
            psa_status_t status = methods->p_init(
                &driver->u.context,
                driver->u.internal.persistent_data,
                driver->location );
            if( status != PSA_SUCCESS )
                return( status );
            status = psa_save_se_persistent_data( driver );
            if( status != PSA_SUCCESS )
                return( status );
        }
    }
    return( PSA_SUCCESS );
}



/****************************************************************/
/* Driver registration */
/****************************************************************/

psa_status_t psa_register_se_driver(
    psa_key_location_t location,
    const psa_drv_se_t *methods)
{
    size_t i;
    psa_status_t status;

    if( methods->hal_version != PSA_DRV_SE_HAL_VERSION )
        return( PSA_ERROR_NOT_SUPPORTED );
    /* Driver table entries are 0-initialized. 0 is not a valid driver
     * location because it means a transparent key. */
#if defined(static_assert)
    static_assert( PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
                   "Secure element support requires 0 to mean a local key" );
#endif
    if( location == PSA_KEY_LOCATION_LOCAL_STORAGE )
        return( PSA_ERROR_INVALID_ARGUMENT );
    if( location > PSA_MAX_SE_LOCATION )
        return( PSA_ERROR_NOT_SUPPORTED );

    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
    {
        if( driver_table[i].location == 0 )
            break;
        /* Check that location isn't already in use up to the first free
         * entry. Since entries are created in order and never deleted,
         * there can't be a used entry after the first free entry. */
        if( driver_table[i].location == location )
            return( PSA_ERROR_ALREADY_EXISTS );
    }
    if( i == PSA_MAX_SE_DRIVERS )
        return( PSA_ERROR_INSUFFICIENT_MEMORY );

    driver_table[i].location = location;
    driver_table[i].methods = methods;
    driver_table[i].u.internal.persistent_data_size =
        methods->persistent_data_size;

    if( methods->persistent_data_size != 0 )
    {
        driver_table[i].u.internal.persistent_data =
            mbedtls_calloc( 1, methods->persistent_data_size );
        if( driver_table[i].u.internal.persistent_data == NULL )
        {
            status = PSA_ERROR_INSUFFICIENT_MEMORY;
            goto error;
        }
        /* Load the driver's persistent data. On first use, the persistent
         * data does not exist in storage, and is initialized to
         * all-bits-zero by the calloc call just above. */
        status = psa_load_se_persistent_data( &driver_table[i] );
        if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST )
            goto error;
    }

    return( PSA_SUCCESS );

error:
    memset( &driver_table[i], 0, sizeof( driver_table[i] ) );
    return( status );
}

void psa_unregister_all_se_drivers( void )
{
    size_t i;
    for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ )
    {
        if( driver_table[i].u.internal.persistent_data != NULL )
            mbedtls_free( driver_table[i].u.internal.persistent_data );
    }
    memset( driver_table, 0, sizeof( driver_table ) );
}



/****************************************************************/
/* The end */
/****************************************************************/

#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
