/*
 *  PSA ITS simulator over stdio files.
 */
/*  Copyright (C) 2018, 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)
 */

#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#endif

#if defined(MBEDTLS_PSA_ITS_FILE_C)

#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_snprintf   snprintf
#endif

#if defined(_WIN32)
#include <windows.h>
#endif

#include "psa_crypto_its.h"

#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#define PSA_ITS_STORAGE_PREFIX ""

#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx"
#define PSA_ITS_STORAGE_SUFFIX ".psa_its"
#define PSA_ITS_STORAGE_FILENAME_LENGTH         \
    ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \
      16 + /*UID (64-bit number in hex)*/                               \
      sizeof( PSA_ITS_STORAGE_SUFFIX ) - 1 + /*suffix without terminating 0*/ \
      1 /*terminating null byte*/ )
#define PSA_ITS_STORAGE_TEMP \
    PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX

/* The maximum value of psa_storage_info_t.size */
#define PSA_ITS_MAX_SIZE 0xffffffff

#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0"
#define PSA_ITS_MAGIC_LENGTH 8

/* As rename fails on Windows if the new filepath already exists,
 * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead.
 * Returns 0 on success, nonzero on failure. */
#if defined(_WIN32)
#define rename_replace_existing( oldpath, newpath ) \
    ( ! MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING ) )
#else
#define rename_replace_existing( oldpath, newpath ) rename( oldpath, newpath )
#endif

typedef struct
{
    uint8_t magic[PSA_ITS_MAGIC_LENGTH];
    uint8_t size[sizeof( uint32_t )];
    uint8_t flags[sizeof( psa_storage_create_flags_t )];
} psa_its_file_header_t;

static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename )
{
    /* Break up the UID into two 32-bit pieces so as not to rely on
     * long long support in snprintf. */
    mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH,
                      "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s",
                      PSA_ITS_STORAGE_PREFIX,
                      (unsigned long) ( uid >> 32 ),
                      (unsigned long) ( uid & 0xffffffff ),
                      PSA_ITS_STORAGE_SUFFIX );
}

static psa_status_t psa_its_read_file( psa_storage_uid_t uid,
                                       struct psa_storage_info_t *p_info,
                                       FILE **p_stream )
{
    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
    psa_its_file_header_t header;
    size_t n;

    *p_stream = NULL;
    psa_its_fill_filename( uid, filename );
    *p_stream = fopen( filename, "rb" );
    if( *p_stream == NULL )
        return( PSA_ERROR_DOES_NOT_EXIST );

    n = fread( &header, 1, sizeof( header ), *p_stream );
    if( n != sizeof( header ) )
        return( PSA_ERROR_DATA_CORRUPT );
    if( memcmp( header.magic, PSA_ITS_MAGIC_STRING,
                PSA_ITS_MAGIC_LENGTH ) != 0 )
        return( PSA_ERROR_DATA_CORRUPT );

    p_info->size = ( header.size[0] |
                     header.size[1] << 8 |
                     header.size[2] << 16 |
                     header.size[3] << 24 );
    p_info->flags = ( header.flags[0] |
                      header.flags[1] << 8 |
                      header.flags[2] << 16 |
                      header.flags[3] << 24 );
    return( PSA_SUCCESS );
}

psa_status_t psa_its_get_info( psa_storage_uid_t uid,
                               struct psa_storage_info_t *p_info )
{
    psa_status_t status;
    FILE *stream = NULL;
    status = psa_its_read_file( uid, p_info, &stream );
    if( stream != NULL )
        fclose( stream );
    return( status );
}

psa_status_t psa_its_get( psa_storage_uid_t uid,
                          uint32_t data_offset,
                          uint32_t data_length,
                          void *p_data )
{
    psa_status_t status;
    FILE *stream = NULL;
    size_t n;
    struct psa_storage_info_t info;

    status = psa_its_read_file( uid, &info, &stream );
    if( status != PSA_SUCCESS )
        goto exit;
    status = PSA_ERROR_INVALID_ARGUMENT;
    if( data_offset + data_length < data_offset )
        goto exit;
#if SIZE_MAX < 0xffffffff
    if( data_offset + data_length > SIZE_MAX )
        goto exit;
#endif
    if( data_offset + data_length > info.size )
        goto exit;

    status = PSA_ERROR_STORAGE_FAILURE;
#if LONG_MAX < 0xffffffff
    while( data_offset > LONG_MAX )
    {
        if( fseek( stream, LONG_MAX, SEEK_CUR ) != 0 )
            goto exit;
        data_offset -= LONG_MAX;
    }
#endif
    if( fseek( stream, data_offset, SEEK_CUR ) != 0 )
        goto exit;
    n = fread( p_data, 1, data_length, stream );
    if( n != data_length )
        goto exit;
    status = PSA_SUCCESS;

exit:
    if( stream != NULL )
        fclose( stream );
    return( status );
}

psa_status_t psa_its_set( psa_storage_uid_t uid,
                          uint32_t data_length,
                          const void *p_data,
                          psa_storage_create_flags_t create_flags )
{
    psa_status_t status = PSA_ERROR_STORAGE_FAILURE;
    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
    FILE *stream = NULL;
    psa_its_file_header_t header;
    size_t n;

    memcpy( header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH );
    header.size[0] = data_length & 0xff;
    header.size[1] = ( data_length >> 8 ) & 0xff;
    header.size[2] = ( data_length >> 16 ) & 0xff;
    header.size[3] = ( data_length >> 24 ) & 0xff;
    header.flags[0] = create_flags & 0xff;
    header.flags[1] = ( create_flags >> 8 ) & 0xff;
    header.flags[2] = ( create_flags >> 16 ) & 0xff;
    header.flags[3] = ( create_flags >> 24 ) & 0xff;

    psa_its_fill_filename( uid, filename );
    stream = fopen( PSA_ITS_STORAGE_TEMP, "wb" );
    if( stream == NULL )
        goto exit;

    status = PSA_ERROR_INSUFFICIENT_STORAGE;
    n = fwrite( &header, 1, sizeof( header ), stream );
    if( n != sizeof( header ) )
        goto exit;
    n = fwrite( p_data, 1, data_length, stream );
    if( n != data_length )
        goto exit;
    status = PSA_SUCCESS;

exit:
    if( stream != NULL )
    {
        int ret = fclose( stream );
        if( status == PSA_SUCCESS && ret != 0 )
            status = PSA_ERROR_INSUFFICIENT_STORAGE;
    }
    if( status == PSA_SUCCESS )
    {
        if( rename_replace_existing( PSA_ITS_STORAGE_TEMP, filename ) != 0 )
            status = PSA_ERROR_STORAGE_FAILURE;
    }
    remove( PSA_ITS_STORAGE_TEMP );
    return( status );
}

psa_status_t psa_its_remove( psa_storage_uid_t uid )
{
    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
    FILE *stream;
    psa_its_fill_filename( uid, filename );
    stream = fopen( filename, "rb" );
    if( stream == NULL )
        return( PSA_ERROR_DOES_NOT_EXIST );
    fclose( stream );
    if( remove( filename ) != 0 )
        return( PSA_ERROR_STORAGE_FAILURE );
    return( PSA_SUCCESS );
}

#endif /* MBEDTLS_PSA_ITS_FILE_C */
