/*
 *  PSA crypto support for secure element drivers
 */
/*
 *  Copyright (C) 2019, ARM Limited, All Rights Reserved
 *  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.
 *
 *  This file is part of Mbed TLS (https://tls.mbed.org)
 */

#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"
#if !defined(MBEDTLS_PLATFORM_C)
#define mbedtls_calloc calloc
#define mbedtls_free   free
#endif



/****************************************************************/
/* 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 */
