mirror of https://github.com/ARMmbed/mbed-os.git
Merge 61cfe5c4a7
into d723bf9e55
commit
ab94ac61c3
|
@ -4,7 +4,7 @@
|
|||
"present": 1,
|
||||
"main-thread-stack-size": {
|
||||
"help": "The size of the main thread's stack",
|
||||
"value": 4096
|
||||
"value": 16384
|
||||
},
|
||||
"timer-thread-stack-size": {
|
||||
"help": "The size of the timer thread's stack",
|
||||
|
|
|
@ -38,6 +38,9 @@ if("SPIF" IN_LIST MBED_TARGET_LABELS)
|
|||
add_subdirectory(COMPONENT_SPIF)
|
||||
endif()
|
||||
|
||||
if("SECUREF" IN_LIST MBED_TARGET_LABELS)
|
||||
add_subdirectory(COMPONENT_SECUREF)
|
||||
endif()
|
||||
|
||||
target_include_directories(mbed-storage-blockdevice
|
||||
INTERFACE
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Copyright (c) 2020 ARM Limited. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
target_sources(mbed-storage-securef
|
||||
INTERFACE
|
||||
source/SecureFBlockDevice.cpp
|
||||
PRIVATE
|
||||
platform/plat_secure_flash.cpp
|
||||
spi_nor_flash/spi_nor.c
|
||||
)
|
||||
|
||||
target_include_directories(mbed-storage-securef
|
||||
INTERFACE
|
||||
include
|
||||
include/SECUREF
|
||||
PRIVATE
|
||||
platform/include/
|
||||
spi_nor_flash/
|
||||
)
|
||||
add_subdirectory(JEDEC_security_HAL)
|
|
@ -0,0 +1,27 @@
|
|||
#-------------------------------------------------------------------------------
|
||||
# Copyright (c) 2020-2023 Macronix International Co. LTD. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
|
||||
add_library(jedec_security_hal STATIC)
|
||||
|
||||
target_sources(jedec_security_hal
|
||||
PRIVATE
|
||||
JEDEC_security_HAL/jedec_security_hal.c
|
||||
JEDEC_security_HAL/queue.c
|
||||
)
|
||||
|
||||
target_include_directories(jedec_security_hal
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/JEDEC_security_HAL
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/JEDEC_security_HAL/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor_impl
|
||||
)
|
||||
|
||||
add_subdirectory(vendor_impl)
|
|
@ -0,0 +1,24 @@
|
|||
#-------------------------------------------------------------------------------
|
||||
# Copyright (c) 2020-2023 Macronix International Co. LTD. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
|
||||
add_library(jedec_security_hal STATIC)
|
||||
|
||||
target_sources(jedec_security_hal
|
||||
PRIVATE
|
||||
jedec_security_hal.c
|
||||
queue.c
|
||||
)
|
||||
|
||||
target_include_directories(jedec_security_hal
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _CRYPTO_WRAPPER_H_
|
||||
#define _CRYPTO_WRAPPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "include/crypto_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int (*init_t)(void);
|
||||
typedef int (*deinit_t)(void);
|
||||
typedef int (*algorithm_support_t)(int alg);
|
||||
typedef int (*crypto_func_t)(crypto_indicator_t *indicator);
|
||||
typedef int (*key_derive_t)(crypto_indicator_t *indicator, uint32_t *output_key_id);
|
||||
typedef int (*generate_random_t)(uint8_t *odata, uint32_t odata_len);
|
||||
typedef int (*ecdh_gen_key_pair_t)(crypto_indicator_t *indicator);
|
||||
typedef int (*ecdh_gen_shared_secret_t)(crypto_indicator_t *indicator);
|
||||
|
||||
typedef int (*open_key_t)(uint32_t key_id);
|
||||
typedef int (*close_key_t)(uint32_t key_id);
|
||||
typedef int (*destroy_key_t)(uint32_t key_id);
|
||||
typedef int (*export_public_key_t)(uint32_t key_id, uint8_t *key_buf, uint32_t buf_size, uint32_t *actual_size);
|
||||
typedef int (*export_key_t)(uint32_t key_id, uint8_t *key_buf, uint32_t buf_size, uint32_t *actual_size);
|
||||
typedef int (*import_key_t)(uint32_t *key_id, uint8_t *key_buf, uint32_t buf_size, KeyLifeTime lifetime);
|
||||
|
||||
|
||||
typedef struct {
|
||||
init_t init;
|
||||
deinit_t deinit;
|
||||
algorithm_support_t algorithm_support;
|
||||
crypto_func_t crypto_func;
|
||||
key_derive_t key_derive;
|
||||
generate_random_t generate_random;
|
||||
ecdh_gen_key_pair_t ecdh_gen_key_pair;
|
||||
ecdh_gen_shared_secret_t ecdh_gen_shared_secret;
|
||||
|
||||
open_key_t open_key;
|
||||
close_key_t close_key;
|
||||
destroy_key_t destroy_key;
|
||||
export_public_key_t export_public_key;
|
||||
export_key_t export_key;
|
||||
import_key_t import_key;
|
||||
|
||||
} crypto_wrapper_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CRYPTO_WRAPPER_H_ */
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _CRYPTO_DEFS_H_
|
||||
#define _CRYPTO_DEFS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Cryptographic service error code
|
||||
*
|
||||
*/
|
||||
|
||||
#define JEDEC_ERROR_NOTHING -0x1001
|
||||
#define JEDEC_ERROR_AEAD_ENC -0x1002
|
||||
#define JEDEC_ERROR_AEAD_DEC -0x1003
|
||||
#define JEDEC_ERROR_CIPHER_ENC -0x1004
|
||||
#define JEDEC_ERROR_CIPHER_DEC -0x1005
|
||||
#define JEDEC_ERROR_AEAD -0x1006
|
||||
#define JEDEC_ERROR_HMAC -0x1007
|
||||
#define JEDEC_ERROR_KDF -0x1008
|
||||
#define JEDEC_ERROR_MAC_COMPUTE -0x1009
|
||||
#define JEDEC_ERROR_MAC_VERIFY -0x100A
|
||||
#define JEDEC_ERROR_GENERATE_RANDOM -0x100B
|
||||
#define JEDEC_ERROR_OPEN_KEY -0x100C
|
||||
#define JEDEC_ERROR_CLOSE_KEY -0x100D
|
||||
#define JEDEC_ERROR_EXPORT_KEY -0x100E
|
||||
#define JEDEC_ERROR_IMPORT_KEY -0x100F
|
||||
#define JEDEC_ERROR_DESTROY_KEY -0x1010
|
||||
#define JEDEC_ERROR_INVALID_PARAM -0x1011
|
||||
#define JEDEC_ERROR_NOT_SUPPORT -0x1012
|
||||
#define JEDEC_ERROR_GENERATE_KEY -0x1013
|
||||
#define JEDEC_ERROR_KEY_ID_CONFLICT -0x1014
|
||||
#define JEDEC_ERROR_KEY_ID_NOT_FOUND -0x1015
|
||||
#define JEDEC_ERROR_KEY_OPERATION -0x1016
|
||||
#define JEDEC_ERROR_RANDOM_GEN -0x1017
|
||||
#define JEDEC_ERROR_MAC -0x1018
|
||||
#define JEDEC_ERROR_CRYPTO -0x1019
|
||||
|
||||
#define MAX_CIPHER_DATA_SIZE 1024
|
||||
|
||||
#define INVALID_KEY_ID 0 /*!< Invalid key id */
|
||||
#define RESVD_KEY_ID 0xFFFFFFFF /*!< Reserved key id */
|
||||
|
||||
#define ALG_TYPE(ALG) (ALG & 0xFFFFFFF0)
|
||||
|
||||
/* \brief Supported cipher types and modes
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
ALG_NONE = 0x00, // 0x00
|
||||
|
||||
ALG_AES_CCM = 0x10, // 0x10
|
||||
ALG_AES_CCM_128, // 0x11
|
||||
ALG_AES_CCM_192, // 0x12
|
||||
ALG_AES_CCM_256, // 0x13
|
||||
ALG_AES_GCM = 0x20, // 0x20
|
||||
ALG_AES_GCM_128, // 0x21
|
||||
ALG_AES_GCM_192, // 0x22
|
||||
ALG_AES_GCM_256, // 0x23
|
||||
ALG_AES_ECB = 0x30, // 0x30
|
||||
ALG_AES_ECB_128, // 0x31
|
||||
ALG_AES_ECB_192, // 0x32
|
||||
ALG_AES_ECB_256, // 0x33
|
||||
ALG_AES_CBC = 0x40, // 0x40
|
||||
ALG_AES_CBC_128, // 0x41
|
||||
ALG_AES_CBC_192, // 0x42
|
||||
ALG_AES_CBC_256, // 0x43
|
||||
ALG_AES_OFB = 0x50, // 0x50
|
||||
ALG_AES_OFB_128, // 0x51
|
||||
ALG_AES_OFB_192, // 0x52
|
||||
ALG_AES_OFB_256, // 0x53
|
||||
ALG_AES_CTR = 0x60, // 0x60
|
||||
ALG_AES_CTR_128, // 0x61
|
||||
ALG_AES_CTR_192, // 0x62
|
||||
ALG_AES_CTR_256, // 0x63
|
||||
|
||||
ALG_ECDSA = 0x70, // 0x70
|
||||
ALG_ECDSA_SECP192R1, // 0x71
|
||||
ALG_ECDSA_SECP224R1, // 0x72
|
||||
ALG_ECDSA_SECP256R1, // 0x73
|
||||
ALG_ECDSA_SECP384R1, // 0x74
|
||||
ALG_ECDSA_SECP521R1, // 0x75
|
||||
ALG_ECDSA_BP256R1, // 0x76
|
||||
ALG_ECDSA_BP384R1, // 0x77
|
||||
ALG_ECDSA_BP512R1, // 0x78
|
||||
ALG_ECDSA_CURVE25519, // 0x79
|
||||
ALG_ECDSA_SECP192K1, // 0x7A
|
||||
ALG_ECDSA_SECP224K1, // 0x7B
|
||||
ALG_ECDSA_SECP256K1, // 0x7C
|
||||
ALG_ECDSA_CURVE448, // 0x7D
|
||||
|
||||
ALG_ECDH = 0x80, // 0x80
|
||||
ALG_ECDH_SECP192R1, // 0x81
|
||||
ALG_ECDH_SECP224R1, // 0x82
|
||||
ALG_ECDH_SECP256R1, // 0x83
|
||||
ALG_ECDH_SECP384R1, // 0x84
|
||||
ALG_ECDH_SECP521R1, // 0x85
|
||||
ALG_ECDH_BP256R1, // 0x86
|
||||
ALG_ECDH_BP384R1, // 0x87
|
||||
ALG_ECDH_BP512R1, // 0x88
|
||||
ALG_ECDH_CURVE25519, // 0x89
|
||||
ALG_ECDH_SECP192K1, // 0x8A
|
||||
ALG_ECDH_SECP224K1, // 0x8B
|
||||
ALG_ECDH_SECP256K1, // 0x8C
|
||||
|
||||
ALG_HMAC = 0x90, // 0x90
|
||||
ALG_HMAC_SHA_1, // 0x91
|
||||
ALG_HMAC_SHA_224, // 0x92
|
||||
ALG_HMAC_SHA_256, // 0x93
|
||||
ALG_HMAC_SHA_384, // 0x94
|
||||
ALG_HMAC_SHA_512, // 0x95
|
||||
|
||||
ALG_HKDF = 0xA0, // 0xA0
|
||||
ALG_HKDF_SHA_1, // 0xA1
|
||||
ALG_HKDF_SHA_224, // 0xA2
|
||||
ALG_HKDF_SHA_256, // 0xA3
|
||||
ALG_HKDF_SHA_384, // 0xA4
|
||||
ALG_HKDF_SHA_512, // 0xA5
|
||||
} CryptoAlgorithm;
|
||||
|
||||
/**
|
||||
* \brief Supported cryptographic operation properties
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
PROP_NO_SECURITY_OPERATION , /*!< No security operation. */
|
||||
|
||||
PROP_AUTHEN_TAG_DECRYPT_DATA , /*!< Authenticate tag and decrypt data */
|
||||
PROP_AUTHEN_TAG , /*!< Authenticate tag only */
|
||||
PROP_DECRYPT_DATA , /*!< Decrypt data only */
|
||||
|
||||
PROP_ENCRYPT_TAG_DATA , /*!< Encrypt data and generate authenticate tag */
|
||||
PROP_ENCRYPT_TAG , /*!< Generate authenticate tag only */
|
||||
PROP_ENCRYPT_DATA , /*!< Encrypt data only */
|
||||
|
||||
PROP_HMAC_COMPUTE , /*!< Compute Hash-based MAC */
|
||||
PROP_HMAC_VERIFY , /*!< Verify Hash-based MAC */
|
||||
|
||||
PROP_HKDF , /*!< HKDF Extract-Expand */
|
||||
PROP_HKDF_EXTRACT , /*!< HKDF Extract */
|
||||
PROP_HKDF_EXPAND , /*!< HKDF Expand */
|
||||
|
||||
PROP_SIGNATURE_SIGN , /*!< Generate signature */
|
||||
PROP_SIGNATURE_VERIFY , /*!< Verify signature */
|
||||
|
||||
PROP_GEN_KEY_PAIR , /*!< Generate key pair */
|
||||
PROP_GEN_SHARED_SECRET , /*!< Compute shared secret */
|
||||
} CryptoOpProperty;
|
||||
|
||||
typedef enum {
|
||||
RAW_PUB_KEY,
|
||||
UNCOMPRESSED_PUB_KEY,
|
||||
COMPRESSED_PUB_KEY
|
||||
} EcdhPubKeyType;
|
||||
|
||||
typedef enum {
|
||||
KEY_LIFETIME_VOLATILE,
|
||||
KEY_LIFETIME_PERSISTENT,
|
||||
} KeyLifeTime;
|
||||
/**
|
||||
* \brief Cryptographic operation indicator
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
/**
|
||||
* \struct aead
|
||||
*
|
||||
* \brief Structure containing AES-CCM/AES-GCM operation parameters.
|
||||
*/
|
||||
struct {
|
||||
uint32_t key_id;
|
||||
uint32_t key_len;
|
||||
uint8_t *iv;
|
||||
uint32_t iv_len;
|
||||
uint8_t *add;
|
||||
uint32_t add_len;
|
||||
uint8_t *plain_text;
|
||||
uint8_t *cipher_text;
|
||||
uint32_t text_len;
|
||||
uint8_t *tag;
|
||||
uint32_t tag_len;
|
||||
} aead;
|
||||
/**
|
||||
* \struct hkdf
|
||||
*
|
||||
* \brief Structure containing HKDF operation parameters.
|
||||
*/
|
||||
struct {
|
||||
uint32_t ikm_id; /*!< input key material id */
|
||||
uint32_t ikm_len;
|
||||
uint8_t *salt; /*!< optional salt value (a non-secret random value) */
|
||||
uint32_t salt_len;
|
||||
uint32_t prk_id;
|
||||
uint8_t *prk; /*!< pseudo random key (of HashLen octets) */
|
||||
uint32_t prk_len;
|
||||
uint8_t *info; /*!< optional context and application specific information */
|
||||
uint32_t info_len;
|
||||
uint32_t okm_id;
|
||||
uint8_t *okm; /*!< output keying material (of okm_len octets) */
|
||||
uint32_t okm_len; /*!< length of output keying material in octets */
|
||||
} hkdf;
|
||||
/**
|
||||
* \struct cipher
|
||||
*
|
||||
* \brief Structure containing AES CBC/ECB operation parameters.
|
||||
*/
|
||||
struct {
|
||||
uint32_t key_id;
|
||||
uint8_t *iv;
|
||||
uint32_t iv_len;
|
||||
uint8_t *plain_text;
|
||||
uint8_t *cipher_text;
|
||||
uint32_t text_len;
|
||||
} enc_cipher;
|
||||
/**
|
||||
* \struct ecdh
|
||||
*
|
||||
* \brief Structure containing ECDH operation parameters.
|
||||
*/
|
||||
struct {
|
||||
EcdhPubKeyType pub_key_type;
|
||||
uint8_t *pub_key;
|
||||
uint32_t pub_key_id;
|
||||
uint32_t pub_key_len;
|
||||
uint32_t pri_key_id;
|
||||
uint32_t pri_key_len;
|
||||
uint8_t *secret;
|
||||
uint32_t secret_id;
|
||||
uint32_t secret_len;
|
||||
} ecdh;
|
||||
/**
|
||||
* \struct hmac
|
||||
*
|
||||
* \brief Structure containing HMAC operation parameters.
|
||||
*/
|
||||
struct {
|
||||
uint8_t *key;
|
||||
uint32_t key_id;
|
||||
uint32_t key_len;
|
||||
uint8_t *idata;
|
||||
uint32_t idata_len;
|
||||
uint8_t *mac;
|
||||
uint32_t mac_id;
|
||||
uint32_t mac_len;
|
||||
} hmac;
|
||||
};
|
||||
struct {
|
||||
uint8_t import_req;
|
||||
int flag;
|
||||
KeyLifeTime lifetime;
|
||||
int type;
|
||||
} key_attr;
|
||||
uint8_t buf[MAX_CIPHER_DATA_SIZE];
|
||||
/**
|
||||
* \brief Crypto algorithm type.
|
||||
*/
|
||||
CryptoAlgorithm algorithm;
|
||||
/**
|
||||
* \brief Crypto operation property.
|
||||
*/
|
||||
CryptoOpProperty property;
|
||||
} crypto_indicator_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _CRYPTO_DEFS_H_ */
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _ERROR_H_
|
||||
#define _ERROR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int32_t jedec_error_t;
|
||||
|
||||
#define JEDEC_ERROR_NONE 0
|
||||
#define JEDEC_ERROR_SESSION -0x0001
|
||||
#define JEDEC_ERROR_INV_ARGS -0x0002
|
||||
#define JEDEC_ERROR_AUTH_FAIL -0x0003
|
||||
#define JEDEC_ERROR_COMM_FAIL -0x0004
|
||||
#define JEDEC_ERROR_INVALID_ADDR -0x0005
|
||||
#define JEDEC_ERROR_MAX_SESSIONS_REACHED -0x0006
|
||||
#define JEDEC_ERROR_CMD_NOT_SUPPORTED_ON_DEVICE -0x000a
|
||||
#define JEDEC_ERROR_INIT_FAIL -0x000b
|
||||
#define JEDEC_ERROR_NOT_PERMITTED -0x000c
|
||||
#define JEDEC_ERROR_DEVICE_BUSY -0x0011
|
||||
#define JEDEC_ERROR_CMD_PACKET -0x0012
|
||||
#define JEDEC_ERROR_INSUFFICIENT_MEMORY -0x0013
|
||||
#define JEDEC_ERROR_GENERIC -0x0014
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ERROR_H_ */
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _JEDEC_DEFS_H_
|
||||
#define _JEDEC_DEFS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* secure read is supported */
|
||||
#define SECURE_READ
|
||||
/* fixme: These macro could be defined in jedec_config.cmake file */
|
||||
#define PACKET_MAX_LEN 0x400
|
||||
#define MAX_RANDOM_SIZE 0x20
|
||||
#define MAX_REGION_NUM 0x10
|
||||
|
||||
/* Persistent key ids */
|
||||
/* fixme: 0X55AA55 is just a example key id */
|
||||
#define SECUREFLASH_AUTHEN_KEY_ID 0x55AA55 /*!< Authentication key id for secure init/uninit */
|
||||
/**
|
||||
* \brief Region access restriction
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
NONE_PROC, /*!< no access restriction */
|
||||
WR_PROC, /*!< write protection */
|
||||
RD_PROC, /*!< read protection */
|
||||
RW_PROC, /*!< read&write protection */
|
||||
RD_ONLY, /*!< readonly, write is not allowed */
|
||||
} access_restr_t;
|
||||
|
||||
/**
|
||||
* \brief Region protection type
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
LOCK, /*!< need unlock before read/write */
|
||||
CONTINUOUS, /*!< need sign each read/write command */
|
||||
} proc_type_t;
|
||||
|
||||
/**
|
||||
* \brief region attributes
|
||||
*
|
||||
*/
|
||||
typedef struct secure_region_attributes {
|
||||
uint32_t address; /*!< region start address */
|
||||
uint32_t length; /*!< region size */
|
||||
uint32_t root_key_id; /*!< region root key id */
|
||||
uint8_t auth_algo; /*!< region authentication algorithm */
|
||||
uint8_t encr_algo; /*!< region encryption algorithm */
|
||||
uint8_t access_restr; /*!< region access restriction */
|
||||
uint8_t prot_type; /*!< region protection type */
|
||||
} secure_region_attributes_t;
|
||||
|
||||
/**
|
||||
* \brief region link list node
|
||||
*
|
||||
*/
|
||||
typedef struct region_ll_node{
|
||||
secure_region_attributes_t attributes; /*!< region attributes */
|
||||
uint32_t session_key_id; /*!< region session key id */
|
||||
struct region_ll_node *next; /*!< pointer to next node */
|
||||
} region_ll_node_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _JEDEC_DEFS_H_ */
|
|
@ -0,0 +1,587 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "jedec_security_hal.h"
|
||||
#include "include/error.h"
|
||||
|
||||
static jedec_ctx_t ctx = {};
|
||||
|
||||
jedec_error_t jedec_set_vendor(vendor_security_op_t *vendor,
|
||||
crypto_wrapper_t *crypto_wrapper,
|
||||
void *vendor_ctx)
|
||||
{
|
||||
ctx.vendor_security_op = vendor;
|
||||
ctx.crypto_wrapper = crypto_wrapper,
|
||||
ctx.vendor_ctx = vendor_ctx;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_init(uint32_t auth_key_id)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
uint8_t random[MAX_RANDOM_SIZE];
|
||||
|
||||
if (ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
/* Check whether auth_key_id is valid */
|
||||
if (auth_key_id == INVALID_KEY_ID || ctx.vendor_security_op == NULL ||
|
||||
ctx.crypto_wrapper == NULL || ctx.vendor_ctx == NULL) {
|
||||
return JEDEC_ERROR_INV_ARGS;
|
||||
}
|
||||
err = ctx.crypto_wrapper->open_key(auth_key_id);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_KEY_OPERATION;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.crypto_wrapper->generate_random(random, MAX_RANDOM_SIZE);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_RANDOM_GEN;
|
||||
}
|
||||
err = ctx.vendor_security_op->pre_secure_init(ctx.vendor_ctx,
|
||||
random, MAX_RANDOM_SIZE,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->secure_init_packet(ctx.vendor_ctx, auth_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
NULL,
|
||||
0,
|
||||
indicator.hmac.mac,
|
||||
indicator.hmac.mac_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->post_secure_init(ctx.vendor_ctx, &ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
ctx.is_initialized = true;
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_uninit(uint32_t auth_key_id)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
uint8_t random[MAX_RANDOM_SIZE];
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
if (auth_key_id == INVALID_KEY_ID) {
|
||||
return JEDEC_ERROR_INV_ARGS;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.crypto_wrapper->generate_random(random, MAX_RANDOM_SIZE);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_RANDOM_GEN;
|
||||
}
|
||||
err = ctx.vendor_security_op->pre_secure_uninit(ctx.vendor_ctx,
|
||||
random, MAX_RANDOM_SIZE,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->secure_uninit_packet(ctx.vendor_ctx,
|
||||
auth_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
NULL, 0,
|
||||
indicator.hmac.mac,
|
||||
indicator.hmac.mac_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.vendor_security_op->post_secure_uninit(ctx.vendor_ctx, &ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
/* Close root_key_id */
|
||||
err = ctx.crypto_wrapper->close_key(auth_key_id);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_KEY_OPERATION;
|
||||
}
|
||||
ctx.is_initialized = false;
|
||||
memset(&ctx, 0x00, sizeof (jedec_ctx_t));
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_create_session(uint32_t root_key_id, bool verify, uint32_t *session_key_id)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
uint8_t random[MAX_RANDOM_SIZE];
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.crypto_wrapper->generate_random(random, MAX_RANDOM_SIZE);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_RANDOM_GEN;
|
||||
}
|
||||
err = ctx.vendor_security_op->pre_create_session(ctx.vendor_ctx,
|
||||
random, MAX_RANDOM_SIZE,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->create_session_packet(ctx.vendor_ctx,
|
||||
root_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
NULL, 0,
|
||||
NULL, 0);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* derive session key from root key */
|
||||
err = ctx.crypto_wrapper->key_derive(&indicator, session_key_id);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->generate_random(random, MAX_RANDOM_SIZE);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->post_create_session(ctx.vendor_ctx,
|
||||
root_key_id,
|
||||
*session_key_id,
|
||||
random, MAX_RANDOM_SIZE,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_terminate_session(uint32_t session_key_id)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
uint8_t random[MAX_RANDOM_SIZE];
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.crypto_wrapper->generate_random(random, MAX_RANDOM_SIZE);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_RANDOM_GEN;
|
||||
}
|
||||
err = ctx.vendor_security_op->pre_terminate_session(ctx.vendor_ctx,
|
||||
random, MAX_RANDOM_SIZE,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->terminate_session_packet(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
NULL, 0,
|
||||
indicator.hmac.mac,
|
||||
indicator.hmac.mac_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->post_terminate_session(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
/* Destroy companion crypto system session keys */
|
||||
err = ctx.crypto_wrapper->destroy_key(session_key_id);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
jedec_error_t jedec_secure_program(uint32_t addr, const uint8_t *data, uint32_t len,
|
||||
uint32_t session_key_id, uint32_t *bytes_programmed)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.vendor_security_op->pre_secure_program(ctx.vendor_ctx, addr,
|
||||
session_key_id, &ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
err = ctx.vendor_security_op->secure_program_packet(ctx.vendor_ctx,
|
||||
addr, data, len,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
indicator.aead.cipher_text,
|
||||
indicator.aead.text_len,
|
||||
indicator.aead.tag,
|
||||
indicator.aead.tag_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Get secure program response from secure Flash */
|
||||
err = ctx.vendor_security_op->post_secure_program(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from secure Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Parse response from secure Flash */
|
||||
err = ctx.vendor_security_op->parse_secure_program_response(ctx.vendor_ctx,
|
||||
&indicator,
|
||||
bytes_programmed);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_erase(uint32_t addr, uint32_t len, uint32_t session_key_id)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.vendor_security_op->pre_secure_erase(ctx.vendor_ctx, addr, len,
|
||||
session_key_id, &ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
err = ctx.vendor_security_op->secure_erase_packet(ctx.vendor_ctx,
|
||||
addr, len,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
indicator.aead.cipher_text,
|
||||
indicator.aead.text_len,
|
||||
indicator.aead.tag,
|
||||
indicator.aead.tag_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Get secure program response from secure Flash */
|
||||
err = ctx.vendor_security_op->post_secure_erase(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from secure Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Parse response from secure Flash */
|
||||
err = ctx.vendor_security_op->parse_secure_erase_response(ctx.vendor_ctx, &indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_read(uint32_t addr, uint8_t *data, uint32_t len,
|
||||
uint32_t session_key_id, uint32_t *bytes_read)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.vendor_security_op->pre_secure_read(ctx.vendor_ctx, addr,
|
||||
session_key_id, &ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
err = ctx.vendor_security_op->secure_read_packet(ctx.vendor_ctx,
|
||||
addr, len,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
indicator.aead.cipher_text,
|
||||
indicator.aead.text_len,
|
||||
indicator.aead.tag,
|
||||
indicator.aead.tag_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Get secure program response from secure Flash */
|
||||
err = ctx.vendor_security_op->post_secure_read(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from secure Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Parse response from secure Flash */
|
||||
err = ctx.vendor_security_op->parse_secure_read_response(ctx.vendor_ctx,
|
||||
&indicator,
|
||||
data, len,
|
||||
bytes_read);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_copy(uint32_t src_addr, uint32_t dst_addr, uint32_t len,
|
||||
uint32_t session_key_id)
|
||||
{
|
||||
//TODO
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_get_regions_info(region_ll_node_t *region_descr_p,
|
||||
uint32_t session_key_id, int8_t region_index)
|
||||
{
|
||||
jedec_error_t err = JEDEC_ERROR_NONE;
|
||||
crypto_indicator_t indicator = {};
|
||||
bool session_key_valid_flag;
|
||||
uint16_t region_index_start, region_index_end;
|
||||
uint8_t random[MAX_RANDOM_SIZE];
|
||||
|
||||
if (!ctx.is_initialized) {
|
||||
return JEDEC_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
region_ll_node_t *node_ptr = region_descr_p;
|
||||
region_ll_node_t *next_node_ptr = region_descr_p;
|
||||
memset(&indicator, 0x00, sizeof(indicator));
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.vendor_security_op->pre_secure_get_regions_info(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
&session_key_valid_flag,
|
||||
&ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
if (session_key_valid_flag) {
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
}
|
||||
if (region_index < 0) {
|
||||
region_index_start = 0;
|
||||
region_index_end = MAX_REGION_NUM - 1;
|
||||
} else if (region_index < MAX_REGION_NUM) {
|
||||
region_index_start = region_index;
|
||||
region_index_end = region_index;
|
||||
} else {
|
||||
return JEDEC_ERROR_INV_ARGS;
|
||||
}
|
||||
for (uint16_t index = region_index_start; index <= region_index_end; index++) {
|
||||
if (session_key_valid_flag) {
|
||||
err = ctx.crypto_wrapper->generate_random(random, MAX_RANDOM_SIZE);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->secure_get_regions_info_packet(ctx.vendor_ctx,
|
||||
session_key_id,
|
||||
index,
|
||||
random, MAX_RANDOM_SIZE,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.crypto_wrapper->crypto_func(&indicator);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet,
|
||||
ctx.packet_len,
|
||||
NULL,
|
||||
0,
|
||||
indicator.hmac.mac,
|
||||
indicator.hmac.mac_len);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
queue_clear(&ctx.q);
|
||||
err = ctx.vendor_security_op->post_secure_get_regions_info(ctx.vendor_ctx, node_ptr, &ctx.q);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
/* Verify response from secure Flash */
|
||||
if (queue_verify(ctx.crypto_wrapper, &ctx.q) == false) {
|
||||
return JEDEC_ERROR_AUTH_FAIL;
|
||||
}
|
||||
} else {
|
||||
err = ctx.vendor_security_op->secure_get_regions_info_packet(ctx.vendor_ctx,
|
||||
0,
|
||||
index,
|
||||
NULL, 0,
|
||||
ctx.packet, &ctx.packet_len,
|
||||
NULL);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->packet_send(ctx.vendor_ctx,
|
||||
ctx.packet, ctx.packet_len,
|
||||
NULL, 0,
|
||||
NULL, 0);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
err = ctx.vendor_security_op->post_secure_get_regions_info(ctx.vendor_ctx, node_ptr, NULL);
|
||||
if (err != JEDEC_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
next_node_ptr = node_ptr + 1;
|
||||
node_ptr->next = next_node_ptr;
|
||||
node_ptr = next_node_ptr;
|
||||
next_node_ptr->next = NULL;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
jedec_error_t jedec_secure_manage_region(region_ll_node_t *head)
|
||||
{
|
||||
//TODO
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _JEDEC_SECURITY_HAL_H_
|
||||
#define _JEDEC_SECURITY_HAL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "vendor_security_impl.h"
|
||||
#include "crypto_wrapper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
bool is_initialized; /*!< Secure Flash state:Initialized or uninitialized */
|
||||
void *vendor_ctx; /*!< Vendor context */
|
||||
vendor_security_op_t *vendor_security_op; /*!< Vendor specific security operations */
|
||||
crypto_wrapper_t *crypto_wrapper; /*!< Crypto wrapper functions */
|
||||
uint8_t packet[PACKET_MAX_LEN]; /*!< Buffer holding command packet */
|
||||
uint32_t packet_len; /*!< Command packet length */
|
||||
uint8_t verify; /*!< Verification indication of responses from secure Flash */
|
||||
jqueue_t q; /*!< Response queue */
|
||||
} jedec_ctx_t;
|
||||
|
||||
/**
|
||||
* \brief Bind JEDEC context with vendor specific implementation.
|
||||
*
|
||||
* \param[in] vendor Vendor specific implementation
|
||||
* \param[in] vendor_ctx Vendor specific context
|
||||
*
|
||||
*/
|
||||
jedec_error_t jedec_set_vendor(vendor_security_op_t *vendor,
|
||||
crypto_wrapper_t *crypto_wrapper,
|
||||
void *vendor_ctx);
|
||||
|
||||
/**
|
||||
* \brief Set verify flag of packets returned in the queue.
|
||||
*
|
||||
* \param[in] verify Verify indication
|
||||
*
|
||||
*/
|
||||
jedec_error_t jedec_set_verify(uint8_t verify);
|
||||
|
||||
/**
|
||||
* \brief Move the secure Flash's status to initialized status.
|
||||
*
|
||||
* \param[in] auth_key_id Input authenticatoin key id for secure initialization
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
*/
|
||||
jedec_error_t jedec_secure_init(uint32_t auth_key_id);
|
||||
/**
|
||||
* \brief Security uninitialization of secure Flash.
|
||||
*
|
||||
* \param[in] auth_key_id Input authentication key id for secure uninitialization
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
*/
|
||||
jedec_error_t jedec_secure_uninit(uint32_t auth_key_id);
|
||||
/**
|
||||
* \brief Establish a cryptographic session with secure Flash.
|
||||
*
|
||||
* \param[in] root_key_id Preshared root key ID
|
||||
* \param[in] verify Indicate whether subsequent flash responses
|
||||
* within session should be verified
|
||||
* \param[out] session_key_id Generated session key ID
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
* JEDEC_ERROR_MAX_SESSIONS_REACHED - no more sessions may be created
|
||||
*/
|
||||
jedec_error_t jedec_create_session(uint32_t root_key_id, bool verify, uint32_t *session_key_id);
|
||||
/**
|
||||
* \brief Terminate a cryptographic session with secure Flash.
|
||||
*
|
||||
* \param[in] session_key_id Corresponding session key ID
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
*/
|
||||
jedec_error_t jedec_terminate_session(uint32_t session_key_id);
|
||||
/**
|
||||
* \brief Program data to secure Flash.
|
||||
*
|
||||
* \param[in] secureflash Secure Flash to access
|
||||
* \param[in] addr Target address in secure Flash
|
||||
* \param[in] data Data to be programmed to secure Flash
|
||||
* \param[in] len Number of bytes requested to be programmed
|
||||
* \param[in] session_key_id Session key ID
|
||||
* \param[out] bytes_programmed Number of bytes that have been programmed
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
* JEDEC_ERROR_INVALID_ADDR -address is outside addressable flash address space
|
||||
*/
|
||||
jedec_error_t jedec_secure_program(uint32_t addr, const uint8_t *data, uint32_t len,
|
||||
uint32_t session_key_id, uint32_t *bytes_programmed);
|
||||
/**
|
||||
* \brief Erase a sector/block specified by a base address of secure Flash.
|
||||
*
|
||||
* \param[in] secureflash Secure Flash to access
|
||||
* \param[in] addr Address from which to start erase
|
||||
* \param[in] len Number of bytes requested to be programmed
|
||||
* \param[in] session_key_id Session key ID
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
*/
|
||||
jedec_error_t jedec_secure_erase(uint32_t addr, uint32_t len, uint32_t session_key_id);
|
||||
/**
|
||||
* \brief Read protected data from secure Flash.
|
||||
*
|
||||
* \param[in] secureflash Secure Flash to access
|
||||
* \param[in] addr Target (starting) address in secure Flash
|
||||
* \param[in] data Data read from secure Flash
|
||||
* \param[in] len Number of bytes requested to be read
|
||||
* \param[in] session_key_id Session key ID
|
||||
* \param[out] bytes_read Number of bytes that have been read
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
* JEDEC_ERROR_INVALID_ADDR -address is outside addressable flash address space
|
||||
* JEDEC_ERROR_CMD_NOT_SUPPORTED_ON_DEVICE -command not supported by vendor's flash
|
||||
*/
|
||||
jedec_error_t jedec_secure_read(uint32_t addr, uint8_t *data, uint32_t len,
|
||||
uint32_t session_key_id, uint32_t *bytes_read);
|
||||
/**
|
||||
* \brief Copy data from secure Flash one location to another.
|
||||
*
|
||||
* \param[in] secureflash Secure Flash to access
|
||||
* \param[in] src_addr Source address in secure Flash
|
||||
* \param[in] dst_addr Destination address in secure Flash
|
||||
* \param[in] len Number of bytes to copy
|
||||
* \param[in] session_key_id Session key ID
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
* JEDEC_ERROR_INVALID_ADDR -address is outside addressable flash address space
|
||||
* JEDEC_ERROR_CMD_NOT_SUPPORTED_ON_DEVICE -command not supported by vendor's flash
|
||||
*/
|
||||
jedec_error_t jedec_secure_copy(uint32_t src_addr, uint32_t dst_addr, uint32_t len,
|
||||
uint32_t session_key_id);
|
||||
/**
|
||||
* \brief Obtain current secure configuration parameters of secure Flash.
|
||||
*
|
||||
* \param[in] secureflash Secure Flash to access
|
||||
* \param[in/out] region_descr_p Pointer to secure region configuration linked list.
|
||||
* \param[in] session_key_id Session key ID
|
||||
* \param[in] region_idx Region index
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
*/
|
||||
jedec_error_t jedec_secure_get_regions_info(region_ll_node_t *region_descr_p,
|
||||
uint32_t session_key_id, int8_t region_idx);
|
||||
/**
|
||||
* \brief Configure secure Flash regions.
|
||||
*
|
||||
* \param[in] secureflash Secure Flash to access
|
||||
* \param[in] head Pointer to the header of secure regions'
|
||||
* configuration parameters link list
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE - success
|
||||
* JEDEC_ERROR_SESSION - no session has been established
|
||||
* JEDEC_ERROR_INV_ARGS - invalid input arguments
|
||||
* JEDEC_ERROR_AUTH_FAIL - authentication failure
|
||||
* JEDEC_ERROR_COMM_FAIL - communication error
|
||||
* JEDEC_ERROR_CMD_NOT_SUPPORTED_ON_DEVICE - command not supported by vendor's flash
|
||||
*/
|
||||
jedec_error_t jedec_secure_manage_region(region_ll_node_t *head);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _JEDEC_SECURITY_HAL_H_ */
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "queue.h"
|
||||
|
||||
void queue_clear(jqueue_t *q)
|
||||
{
|
||||
q->list.head.next = &q->list.head;
|
||||
q->list.head.prev = &q->list.head;
|
||||
memset(q->buf, 0x00, sizeof(q->buf));
|
||||
q->offset = 0;
|
||||
}
|
||||
|
||||
bool queue_is_empty(jqueue_t *q)
|
||||
{
|
||||
if ((q->list.head.next == NULL) ||
|
||||
(q->list.head.next == &(q->list.head))) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void queue_add(jqueue_t *q, resp_param_t *item)
|
||||
{
|
||||
if ((q->offset + sizeof(jresp_t)) > BUF_SIZE) {
|
||||
return;
|
||||
}
|
||||
jresp_t *r = (jresp_t *)&q->buf[q->offset];
|
||||
q->offset += sizeof(jresp_t);
|
||||
r->node.next = NULL;
|
||||
r->node.prev = NULL;
|
||||
|
||||
r->param.alg = item->alg;
|
||||
r->param.property = item->property;
|
||||
switch (ALG_TYPE(item->alg)) {
|
||||
case ALG_HMAC:
|
||||
r->param.hmac.flag = item->hmac.flag;
|
||||
r->param.hmac.key_id = item->hmac.key_id;
|
||||
r->param.hmac.key_len = item->hmac.key_len;
|
||||
//input data
|
||||
if (((q->offset + item->hmac.idata_len) <= BUF_SIZE) &&
|
||||
(item->hmac.idata != NULL) && (item->hmac.idata_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->hmac.idata, item->hmac.idata_len);
|
||||
r->param.hmac.idata = &q->buf[q->offset];
|
||||
r->param.hmac.idata_len = item->hmac.idata_len;
|
||||
q->offset += item->hmac.idata_len;
|
||||
}
|
||||
//mac
|
||||
if (((q->offset + item->hmac.mac_len) <= BUF_SIZE) &&
|
||||
(item->hmac.mac != NULL) && (item->hmac.mac_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->hmac.mac, item->hmac.mac_len);
|
||||
r->param.hmac.mac = &q->buf[q->offset];
|
||||
r->param.hmac.mac_len = item->hmac.mac_len;
|
||||
q->offset += item->hmac.mac_len;
|
||||
}
|
||||
break;
|
||||
case ALG_AES_GCM:
|
||||
r->param.aead.key_id = item->aead.key_id;
|
||||
//iv
|
||||
if (((q->offset + item->aead.iv_len) <= BUF_SIZE) &&
|
||||
(item->aead.iv != NULL) && (item->aead.iv_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->aead.iv, item->aead.iv_len);
|
||||
r->param.aead.iv = &q->buf[q->offset];
|
||||
r->param.aead.iv_len = item->aead.iv_len;
|
||||
q->offset += item->aead.iv_len;
|
||||
}
|
||||
//aad
|
||||
if (((q->offset + item->aead.aad_len) <= BUF_SIZE) &&
|
||||
(item->aead.aad != NULL) && (item->aead.aad_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->aead.aad, item->aead.aad_len);
|
||||
r->param.aead.aad = &q->buf[q->offset];
|
||||
r->param.aead.aad_len = item->aead.aad_len;
|
||||
q->offset += item->aead.aad_len;
|
||||
}
|
||||
//packet
|
||||
if (((q->offset + item->aead.ciphertext_len) <= BUF_SIZE) &&
|
||||
(item->aead.ciphertext != NULL) && (item->aead.ciphertext_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->aead.ciphertext, item->aead.ciphertext_len);
|
||||
r->param.aead.ciphertext = &q->buf[q->offset];
|
||||
r->param.aead.ciphertext_len = item->aead.ciphertext_len;
|
||||
q->offset += item->aead.ciphertext_len;
|
||||
}
|
||||
//tag
|
||||
if (((q->offset + item->aead.tag_len) <= BUF_SIZE) &&
|
||||
(item->aead.tag != NULL) && (item->aead.tag_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->aead.tag, item->aead.tag_len);
|
||||
r->param.aead.tag = &q->buf[q->offset];
|
||||
r->param.aead.tag_len = item->aead.tag_len;
|
||||
q->offset += item->aead.tag_len;
|
||||
}
|
||||
//plaintext
|
||||
if (((q->offset + item->aead.plaintext_len) <= BUF_SIZE) &&
|
||||
(item->aead.plaintext != NULL) && (item->aead.plaintext_len > 0)) {
|
||||
memcpy(&q->buf[q->offset], item->aead.plaintext, item->aead.plaintext_len);
|
||||
r->param.aead.plaintext = &q->buf[q->offset];
|
||||
r->param.aead.plaintext_len = item->aead.plaintext_len;
|
||||
q->offset += item->aead.plaintext_len;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
r->node.prev = q->list.head.prev;
|
||||
r->node.next = &(q->list.head);
|
||||
r->node.next->prev = &r->node;
|
||||
r->node.prev->next = &r->node;
|
||||
}
|
||||
|
||||
void queue_get(jqueue_t *q, resp_param_t *item)
|
||||
{
|
||||
jresp_t *r = (jresp_t *)q->list.head.next;
|
||||
if (queue_is_empty(q)) {
|
||||
return;
|
||||
}
|
||||
switch (ALG_TYPE(r->param.alg)) {
|
||||
case ALG_HMAC:
|
||||
memcpy (item, &r->param, sizeof (resp_param_t));
|
||||
q->offset -= r->param.hmac.idata_len;
|
||||
q->offset -= r->param.hmac.mac_len;
|
||||
q->offset -= sizeof(jresp_t);
|
||||
break;
|
||||
case ALG_AES_GCM:
|
||||
memcpy (item, &r->param, sizeof (resp_param_t));
|
||||
q->offset -= r->param.aead.iv_len;
|
||||
q->offset -= r->param.aead.aad_len;
|
||||
q->offset -= r->param.aead.ciphertext_len;
|
||||
q->offset -= r->param.aead.tag_len;
|
||||
q->offset -= sizeof(jresp_t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
r->node.prev->next = r->node.next;
|
||||
r->node.next->prev = r->node.prev;
|
||||
r->node.prev = NULL;
|
||||
r->node.next = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Verify secure Flash responses stored in queque.
|
||||
*
|
||||
* \param[in] crypto_wrapper Pointer of crypto wrapper
|
||||
* \param[in] queue Queue of secure Flash responses
|
||||
*
|
||||
* \return true if crypto verification success,
|
||||
* or false if crypto verification fail
|
||||
*/
|
||||
bool queue_verify(crypto_wrapper_t *crypto_wrapper, jqueue_t *queue)
|
||||
{
|
||||
resp_param_t response;
|
||||
crypto_indicator_t indicator = {};
|
||||
|
||||
while (!queue_is_empty(queue)) {
|
||||
queue_get(queue, &response);
|
||||
indicator.algorithm = response.alg;
|
||||
indicator.property = response.property;
|
||||
switch (ALG_TYPE(response.alg)) {
|
||||
case ALG_HMAC:
|
||||
if ((response.hmac.key_id != 0) &&
|
||||
(response.hmac.idata != NULL) && (response.hmac.idata_len > 0) ||
|
||||
(response.hmac.mac == NULL) && (response.hmac.mac_len > 0)) {
|
||||
indicator.key_attr.flag = response.hmac.flag;
|
||||
indicator.hmac.key_id = response.hmac.key_id;
|
||||
indicator.hmac.key_len = response.hmac.key_len;
|
||||
indicator.hmac.idata = response.hmac.idata;
|
||||
indicator.hmac.idata_len = response.hmac.idata_len;
|
||||
indicator.hmac.mac = response.hmac.mac;
|
||||
indicator.hmac.mac_len = response.hmac.mac_len;
|
||||
if (crypto_wrapper->crypto_func(&indicator) != JEDEC_ERROR_NONE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ALG_AES_GCM:
|
||||
if ((response.aead.key_id != 0) &&
|
||||
(response.aead.iv != NULL) && (response.aead.iv_len > 0) &&
|
||||
(response.aead.aad != NULL) && (response.aead.aad_len > 0) &&
|
||||
(response.aead.ciphertext != NULL) && (response.aead.ciphertext_len > 0) &&
|
||||
(response.aead.tag != NULL) && (response.aead.tag_len > 0)) {
|
||||
indicator.property = PROP_AUTHEN_TAG;
|
||||
indicator.aead.key_id = response.aead.key_id;
|
||||
indicator.aead.iv = response.aead.iv;
|
||||
indicator.aead.iv_len = response.aead.iv_len;
|
||||
indicator.aead.add = response.aead.aad;
|
||||
indicator.aead.add_len = response.aead.aad_len;
|
||||
indicator.aead.cipher_text = response.aead.ciphertext;
|
||||
indicator.aead.text_len = response.aead.ciphertext_len;
|
||||
indicator.aead.tag = response.aead.tag;
|
||||
indicator.aead.tag_len = response.aead.tag_len;
|
||||
if (crypto_wrapper->crypto_func(&indicator) != JEDEC_ERROR_NONE) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ALG_NONE:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _QUEUE_H_
|
||||
#define _QUEUE_H_
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "crypto_wrapper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BUF_SIZE (4*1024)
|
||||
|
||||
typedef struct jnode {
|
||||
struct jnode *next;
|
||||
struct jnode *prev;
|
||||
} jnode_t;
|
||||
|
||||
typedef struct {
|
||||
jnode_t head;
|
||||
} jlist_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t buf[BUF_SIZE];
|
||||
uint16_t offset;
|
||||
jlist_t list;
|
||||
} jqueue_t;
|
||||
|
||||
/** Response cipher type */
|
||||
enum cipher_type {
|
||||
HMAC,
|
||||
AEAD,
|
||||
ENC_CIPHER,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
CryptoAlgorithm alg;
|
||||
CryptoOpProperty property;
|
||||
union {
|
||||
struct {
|
||||
uint32_t key_id;
|
||||
uint8_t key_len;
|
||||
uint8_t *idata;
|
||||
uint16_t idata_len;
|
||||
uint8_t *mac;
|
||||
uint16_t mac_len;
|
||||
uint8_t flag;
|
||||
} hmac;
|
||||
struct {
|
||||
uint32_t key_id;
|
||||
uint8_t *iv;
|
||||
uint16_t iv_len;
|
||||
uint8_t *aad;
|
||||
uint16_t aad_len;
|
||||
uint8_t *tag;
|
||||
uint16_t tag_len;
|
||||
uint8_t *ciphertext;
|
||||
uint16_t ciphertext_len;
|
||||
uint8_t *plaintext;
|
||||
uint16_t plaintext_len;
|
||||
uint8_t flag;
|
||||
} aead;
|
||||
struct {
|
||||
uint32_t key_id;
|
||||
uint8_t *iv;
|
||||
uint16_t iv_len;
|
||||
uint8_t *ciphertext;
|
||||
uint16_t ciphertext_len;
|
||||
uint8_t *plaintext;
|
||||
uint16_t plaintext_len;
|
||||
uint8_t flag;
|
||||
} enc_cipher;
|
||||
};
|
||||
} resp_param_t;
|
||||
|
||||
typedef struct {
|
||||
jnode_t node;
|
||||
resp_param_t param;
|
||||
} jresp_t;
|
||||
|
||||
/**
|
||||
* \brief Clear queue.
|
||||
*
|
||||
* \param[in] q Pointer to the queue
|
||||
*
|
||||
* \return NULL
|
||||
*/
|
||||
void queue_clear(jqueue_t *q);
|
||||
/**
|
||||
* \brief Check whether queue is empty.
|
||||
*
|
||||
* \param[in] q Pointer to the queue
|
||||
*
|
||||
* \return 1 if empty, otherwise 0
|
||||
*/
|
||||
bool queue_is_empty(jqueue_t *q);
|
||||
/**
|
||||
* \brief Add a response item to the queue.
|
||||
*
|
||||
* \param[in] q Pointer to the queue
|
||||
* \param[in] item Response item
|
||||
* \return NULL
|
||||
*/
|
||||
void queue_add(jqueue_t *q, resp_param_t *item);
|
||||
/**
|
||||
* \brief Get a response item from the queue.
|
||||
*
|
||||
* \param[in] q Pointer to the queue
|
||||
* \param[in] item Response item
|
||||
* \return NULL
|
||||
*/
|
||||
void queue_get(jqueue_t *q, resp_param_t *item);
|
||||
|
||||
/**
|
||||
* \brief Verify secure Flash responses stored in queque.
|
||||
*
|
||||
* \param[in] crypto_wrapper Pointer of crypto wrapper
|
||||
* \param[in] queue Queue of secure Flash responses
|
||||
*
|
||||
* \return true if crypto verification success,
|
||||
* or false if crypto verification fail
|
||||
*/
|
||||
bool queue_verify(crypto_wrapper_t *crypto_wrapper, jqueue_t *queue);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _QUEUE_H_ */
|
|
@ -0,0 +1,471 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _VENDOR_IMPL_H_
|
||||
#define _VENDOR_IMPL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "include/jedec_defs.h"
|
||||
#include "queue.h"
|
||||
#include "crypto_wrapper.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief vendor specific security operations
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Vendor id.
|
||||
*/
|
||||
uint8_t vendor_id;
|
||||
/**
|
||||
* \brief Pre create session.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] nonce Host input nonce
|
||||
* \param[in] nonce_len Host nonce length
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_create_session)(void *vendor_ctx, uint8_t *nonce,
|
||||
uint32_t nonce_len, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack create session packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] root_key_id Associated root key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*create_session_packet)(void *vendor_ctx, uint32_t root_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post create session.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] root_key_id Associated root key id
|
||||
* \param[in] session_key_id created session key id
|
||||
* \param[in] nonce Nonce
|
||||
* \param[in] nonce_len Nonce length
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_create_session)(void *vendor_ctx, uint32_t root_key_id,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *nonce, uint32_t nonce_len,
|
||||
jqueue_t *resp_queue);
|
||||
#if defined(SESSION_CONFIRMATION)
|
||||
int32_t (*pre_confirm_session)();
|
||||
int32_t (*confirm_session_packet)();
|
||||
int32_t (*post_confirm_session)();
|
||||
#endif
|
||||
/**
|
||||
* \brief Pre terminate session.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] nonce Host input nonce
|
||||
* \param[in] nonce_len Host nonce length
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_terminate_session)(void *vendor_ctx, uint8_t *nonce,
|
||||
uint32_t nonce_len, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack terminate session packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*terminate_session_packet)(void *vendor_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post terminate session.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_terminate_session)(void *vendor_ctx,
|
||||
uint32_t session_key_id,
|
||||
jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pre secure init.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] nonce Host input nonce
|
||||
* \param[in] nonce_len Host nonce length
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_secure_init)(void *vendor_ctx, uint8_t *nonce,
|
||||
uint32_t nonce_len, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack secure init packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] root_key_id Associated root key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*secure_init_packet)(void *vendor_ctx, uint32_t root_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post secure init.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_secure_init)(void *vendor_ctx, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pre secure uninit.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] nonce Host input nonce
|
||||
* \param[in] nonce_len Host nonce length
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_secure_uninit)(void *vendor_ctx, uint8_t *nonce,
|
||||
uint32_t nonce_len, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack secure uninit packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] root_key_id Associated root key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*secure_uninit_packet)(void *vendor_ctx, uint32_t root_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post secure uninit.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_secure_uninit)(void *vendor_ctx, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pre secure program.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] addr Destination address
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_secure_program)(void *vendor_ctx, uint32_t addr,
|
||||
uint32_t session_key_id, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack secure program packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] addr Destination address
|
||||
* \param[in] data Pointer to source data
|
||||
* \param[in] len Data length
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*secure_program_packet)(void *vendor_ctx, uint32_t addr,
|
||||
const uint8_t *data, uint32_t len,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post secure program.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] resp_queue Pointer to response queue holding responses from flash
|
||||
* \param[in] resp_packet_buffer Buffer to hold secure program response from flash
|
||||
* \param[out] resp_packet_buffer_size Actual secure program response size
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* (if secure program response also needs crypto operations)
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_secure_program)(void *vendor_ctx, jqueue_t *resp_queue,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *resp_packet_buffer,
|
||||
uint32_t *resp_packet_buffer_size,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Parse secure program response.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] indicator Indicator holding crypto algorithm parameters
|
||||
* \param[out] bytes_programmed Actual programmed bytes
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*parse_secure_program_response)(void *vendor_ctx,
|
||||
crypto_indicator_t *indicator,
|
||||
uint32_t *bytes_programmed);
|
||||
/**
|
||||
* \brief Pre secure erase.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] addr Destination address
|
||||
* \param[in] len Erase size
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_secure_erase)(void *vendor_ctx, uint32_t addr, uint32_t len,
|
||||
uint32_t session_key_id, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack secure erase packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] addr Destination address
|
||||
* \param[in] len Erase size
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*secure_erase_packet)(void *vendor_ctx, uint32_t addr, uint32_t len,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post secure erase.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] resp_queue Pointer to response queue holding responses from flash
|
||||
* \param[in] resp_packet_buffer Buffer to hold secure erase response from flash
|
||||
* \param[out] resp_packet_buffer_size Actual secure erase response size
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* (if secure erase response also needs crypto operations)
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_secure_erase)(void *vendor_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *resp_packet_buffer,
|
||||
uint32_t *resp_packet_buffer_size,
|
||||
crypto_indicator_t *indicator,
|
||||
jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Parse secure erase response.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*parse_secure_erase_response)(void *vendor_ctx,
|
||||
crypto_indicator_t *indicator);
|
||||
#if defined(SECURE_COPY)
|
||||
int32_t (*pre_secure_copy)();
|
||||
int32_t (*secure_copy_packet)();
|
||||
int32_t (*post_secure_copy)();
|
||||
int32_t (*parse_secure_copy_response)();
|
||||
#endif
|
||||
#if defined(SECURE_READ)
|
||||
/**
|
||||
* \brief Pre secure read.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] addr Target address
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_secure_read)(void *vendor_ctx, uint32_t addr,
|
||||
uint32_t session_key_id, jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack secure read packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] addr Target address
|
||||
* \param[in] len Data length
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*secure_read_packet)(void *vendor_ctx, uint32_t addr,
|
||||
uint32_t len, uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post secure read.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] resp_queue Pointer to response queue holding responses from flash
|
||||
* \param[in] resp_packet_buffer Buffer to hold secure read response from flash
|
||||
* \param[out] resp_packet_buffer_size Actual secure read response size
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* (if secure read response also needs crypto operations)
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_secure_read)(void *vendor_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *resp_packet_buffer,
|
||||
uint32_t *resp_packet_buffer_size,
|
||||
crypto_indicator_t *indicator,
|
||||
jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Parse secure read response.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] indicator Indicator holding crypto algorithm parameters
|
||||
* \param[out] data Buffer to hold read data
|
||||
* \param[in] data_len Read data length
|
||||
* \param[out] bytes_read Actual read bytes
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*parse_secure_read_response)(void *vendor_ctx,
|
||||
crypto_indicator_t *indicator,
|
||||
uint8_t *data, uint32_t data_len,
|
||||
uint32_t *bytes_read);
|
||||
#endif
|
||||
/**
|
||||
* \brief Pre get regions' information in security.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[out] session_key_valid_flag Session key valid flag
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*pre_secure_get_regions_info)(void *vendor_ctx,
|
||||
uint32_t session_key_id,
|
||||
bool *session_key_valid_flag,
|
||||
jqueue_t *resp_queue);
|
||||
/**
|
||||
* \brief Pack get regions' information in security packet.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] session_key_id Associated session key id
|
||||
* \param[in] region_index Region index
|
||||
* \param[in] nonce Nonce
|
||||
* \param[in] nonce_len Nonce length
|
||||
* \param[in] packet Pointer to packet
|
||||
* \param[in] packet_len Actual packet length
|
||||
* \param[out] indicator Indicator holding crypto algorithm parameters
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*secure_get_regions_info_packet)(void *vendor_ctx,
|
||||
uint32_t session_key_id,
|
||||
int8_t region_index,
|
||||
uint8_t *nonce, uint32_t nonce_len,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Post get regions' information in security.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] region_descr_p Pointer to the link list holding region description
|
||||
* \param[out] resp_queue Pointer to response queue holding responses from flash
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*post_secure_get_regions_info)(void *vendor_ctx,
|
||||
region_ll_node_t *region_descr_p,
|
||||
jqueue_t *resp_queue);
|
||||
#if defined(SECURE_REGION_MANAGE)
|
||||
int32_t (*pre_secure_manage_region)(void *vendor_ctx);
|
||||
int32_t (*secure_manage_region_packet)(void *vendor_ctx);
|
||||
int32_t (*post_secure_manage_region)(void *vendor_ctx);
|
||||
#endif
|
||||
/**
|
||||
* \brief Send security command packet to secure flash.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in/out] packet_out Pointer to command packet
|
||||
* \param[in] packet_len Current packet length without cipher and mac
|
||||
* \param[in] cipher_text Pointer to cipher text
|
||||
* \param[in] cipher_text_len Cipher text length
|
||||
* \param[in] mac Pointer to mac
|
||||
* \param[in] mac_len Mac length
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*packet_send)(void *vendor_ctx,
|
||||
uint8_t *packet_out, uint16_t packet_len,
|
||||
uint8_t *cipher_text, uint16_t cipher_text_len,
|
||||
uint8_t *mac, uint16_t mac_len);
|
||||
/**
|
||||
* \brief Receive security command response packet from secure flash.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] packet_in Pointer to response packet
|
||||
* \param[in] packet_len Response packet length
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*packet_receive)(void *vendor_ctx,
|
||||
uint8_t *packet_in, uint16_t packet_len);
|
||||
} vendor_security_op_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VENDOR_IMPL_H_ */
|
|
@ -0,0 +1,92 @@
|
|||
Getting started
|
||||
==================
|
||||
|
||||
JEDEC have published the [JESD261 standard](https://www.jedec.org/standards-documents/docs/jesd261), titled Serial NOR Security
|
||||
Hardware Abstraction Layer(HAL). This standard defines a software layer to provide
|
||||
a uniform interface for cryptographic operations on compliant Secure Flash devices.
|
||||
|
||||
JESD261 HAL enables manufacturer-neutral communication with secure Flash devices.
|
||||
Security features introduced in JESD261 include session-based communication, secure program
|
||||
and erase operations, as well as partitioning of the Flash device into protected regions,
|
||||
that are available through an application interface. JESD261 defines rules for implementing
|
||||
this application interface to simplify the use and evaluation of these common security features
|
||||
accross secure Flash vendors.
|
||||
|
||||
**************
|
||||
## Design concept
|
||||
|
||||
JEDEC security HAL module could be compiled for use within different OSes and software platforms.
|
||||
In this design, this module consits of JEDEC security HAL API layer and vendor specific implementation layer.
|
||||
|
||||
JEDEC security HAL API layer implements the interfaces defined in JEDEC JESD261 standard.
|
||||
And calls the pre-binding specific sub-steps implemented in vendor specific implementation layer.
|
||||
Besides, the JEDEC security HAL API layer calls crypto services via vendor specific crypto wrapper functions.
|
||||
Currently, mbedtls library and TF-M PSA crypto services are both supported.
|
||||
|
||||
Vendor specific implementations layer provides specific sub-steps implementaion required by
|
||||
JEDEC security HAL API layer. In addition, this layer also includes the specific implementation
|
||||
of secure Flash provisioning which should be performed before deployment.
|
||||
|
||||
Code structure
|
||||
--------------
|
||||
```bash
|
||||
TG424_3/
|
||||
├─JEDEC_security_HAL --------------------------------> JEDEC security HAL API layer
|
||||
│ │ crypto_wrapper.h ------------------------------> Header file for crypto wrapper functions
|
||||
│ │ jedec_security_hal.c ---------------------------> JEDEC security HAL API implementation
|
||||
│ │ jedec_security_hal.h ---------------------------> Header file for JEDEC security HAL API layer
|
||||
│ │ queue.c ----------------------------------------> Queue operations implementation
|
||||
│ │ queue.h ----------------------------------------> Queue operations definition
|
||||
│ │ vendor_security_impl.h --------------------------> Header file for vendor specific implementation of security HAL sub-steps
|
||||
│ │
|
||||
│ └─include
|
||||
│
|
||||
└─vendor_impl -----------------------------------------> Flash vendors specific implementation
|
||||
│ vendor_provisioning_impl.h -------------------> Header file for vendor specific secure flash provisioning operations
|
||||
│ vendor_secureflash.h --------------------------> Vendor secure flash definitions
|
||||
│ vendor_secureflash_defs.h ----------------------> Vendor secure flash informations
|
||||
│
|
||||
├─macronix
|
||||
│ ├─armorflash_mx75 -----------------------------> The specific implementations for Macronix MX75 ArmorFlash
|
||||
│ │
|
||||
│ └─armorflash_mx78 -----------------------------> The specific implementations for Macronix MX78 ArmorFlash
|
||||
│ │ libmx78_armor_lib.a --------------------> Binary library of MX78 ArmorFlash driver
|
||||
│ │ mx78_armor.c ---------------------------> The specific implementations of JEDEC secuiry HAL sub-steps for Macronix MX78 ArmorFlash
|
||||
│ │ mx78_armor.h
|
||||
│ │ mx78_armor_lib.h
|
||||
│ │ secureflash_layout.h -------------------> The specific parameters and secure region layout of MX78 ArmorFlash
|
||||
│ │
|
||||
│ ├─crypto_wrapper ---------------------------> The specific crypto wrapper functions for Macronix MX78 ArmorFlash
|
||||
│ │ crypto_wrapper_mbedtls.c -----------> The specific crypto wrapper functions based on mbedtls library
|
||||
│ │ crypto_wrapper_psa.c --------------> The specific crypto wrapper functions based on Trusted Firmware-M crypto service
|
||||
│ │
|
||||
│ └─provisioning ----------------------------> The specific provisioning implementation for Macronix MX78 ArmorFlash
|
||||
│ libmx78_armor_provision_lib.a ------> Binary library of MX78 ArmorFlash provisioning driver
|
||||
│ mx78_armor_provision.h
|
||||
│
|
||||
└─vendor_template --------------------------------> Reserved vendor specific implementation for other secure Flash vendors reference
|
||||
```
|
||||
********
|
||||
## Examples
|
||||
|
||||
This JEDEC security HAL implementation has been integrated and tested with following OSes and software platforms.
|
||||
|
||||
- [Arm Mbed OS](https://www.arm.com/products/development-tools/embedded-and-software/mbed-os)
|
||||
|
||||
For Arm Mbed OS, JEDEC security HAL is integrated in the COMPONENT_SECUREF. The source code is available on [github](https://github.com/macronix/).
|
||||
|
||||
```
|
||||
git clone -b macronix_secureflash_TG424_3 --recursive https://github.com/macronix/mbed-os
|
||||
```
|
||||
|
||||
|
||||
|
||||
- [Arm Trusted Firmware-M](https://tf-m-user-guide.trustedfirmware.org/index.html)
|
||||
|
||||
For Arm Trusted Firmware-M, JEDEC security HAL is integrated in the ETSS partition which provides solution for supporting secure Flash in Arm Trusted Firmware-M framework. The source code is available on [github](https://github.com/macronix/).
|
||||
|
||||
```
|
||||
git clone -b macronix_secureflash_TG424_3 --recursive https://github.com/macronix/tf-m-extras
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#-------------------------------------------------------------------------------
|
||||
# Copyright (c) 2020-2023 Macronix International Co. LTD. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
|
||||
add_subdirectory(${SECUREFLASH_TYPE})
|
|
@ -0,0 +1 @@
|
|||
Reserved for Macronix MX75 ArmorFlash.
|
|
@ -0,0 +1,85 @@
|
|||
#-------------------------------------------------------------------------------
|
||||
# Copyright (c) 2020-2023 Macronix International Co. LTD. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
cmake_policy(SET CMP0079 NEW)
|
||||
|
||||
if (CRYPTO_MBEDTLS AND CRYPTO_PSA)
|
||||
Message(FATAL_ERROR "CRYPTO_MBEDTLS and CRYPTO_PSA both enabled!")
|
||||
endif()
|
||||
if (NOT CRYPTO_MBEDTLS AND NOT CRYPTO_PSA)
|
||||
Message(FATAL_ERROR "CRYPTO_MBEDTLS and CRYPTO_PSA both disabled!")
|
||||
endif()
|
||||
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/libmx78_armor_lib.a)
|
||||
Message(FATAL_ERROR "libmx78_armor_lib.a should be download and put under current directory")
|
||||
else()
|
||||
add_library(mx78_armor_lib STATIC IMPORTED)
|
||||
set_target_properties(mx78_armor_lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libmx78_armor_lib.a)
|
||||
set_target_properties(mx78_armor_lib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
add_library(mx78_armor STATIC)
|
||||
target_include_directories(mx78_armor
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../include
|
||||
)
|
||||
|
||||
target_compile_definitions(mx78_armor
|
||||
PRIVATE
|
||||
$<$<BOOL:${SECUREFLASH_PROVISION}>:SECUREFLASH_PROVISION>
|
||||
ETSS_PROV_DEVELOPER_MODE=${ETSS_PROV_DEVELOPER_MODE}
|
||||
$<$<BOOL:${MULTI_CLIENT_ISOLATION}>:MULTI_CLIENT_ISOLATION>
|
||||
$<$<BOOL:${SECUREFLASH_DEBUG}>:SECUREFLASH_DEBUG>
|
||||
$<$<BOOL:${MX78_ARMOR_TEST_MODE}>:MX78_ARMOR_TEST_MODE>
|
||||
$<$<BOOL:${CRYPTO_MBEDTLS}>:CRYPTO_MBEDTLS>
|
||||
$<$<BOOL:${CRYPTO_PSA}>:CRYPTO_PSA>
|
||||
)
|
||||
|
||||
target_sources(mx78_armor
|
||||
PRIVATE
|
||||
mx78_armor.c
|
||||
$<$<BOOL:${CRYPTO_PSA}>:${CMAKE_CURRENT_SOURCE_DIR}/crypto_wrapper/crypto_wrapper_psa.c>
|
||||
$<$<BOOL:${CRYPTO_MBEDTLS}>:${CMAKE_CURRENT_SOURCE_DIR}/crypto_wrapper/crypto_wrapper_mbedtls.c>
|
||||
)
|
||||
|
||||
target_link_libraries(mx78_armor
|
||||
PRIVATE
|
||||
psa_interface
|
||||
platform_s
|
||||
tfm_sprt
|
||||
secureflash_platform
|
||||
spi_nor_driver
|
||||
mx78_armor_lib
|
||||
INTERFACE
|
||||
platform_common_interface
|
||||
)
|
||||
|
||||
target_link_libraries(jedec_security_hal
|
||||
PRIVATE
|
||||
mx78_armor
|
||||
)
|
||||
if(SECUREFLASH_PROVISION)
|
||||
target_include_directories(mx78_armor
|
||||
PRIVATE
|
||||
provisioning
|
||||
)
|
||||
|
||||
|
||||
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/provisioning/libmx78_armor_provision_lib.a)
|
||||
Message(FATAL_ERROR "libmx78_armor_provision_lib.a should be download and put under provisioning directory")
|
||||
else()
|
||||
add_library(mx78_armor_provision_lib STATIC IMPORTED)
|
||||
set_target_properties(mx78_armor_provision_lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/provisioning/libmx78_armor_provision_lib.a)
|
||||
set_target_properties(mx78_armor_provision_lib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/provisioning)
|
||||
endif()
|
||||
|
||||
target_link_libraries(mx78_armor
|
||||
PRIVATE
|
||||
mx78_armor_provision_lib
|
||||
)
|
||||
endif()
|
|
@ -0,0 +1,763 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
|
||||
#ifdef CRYPTO_MBEDTLS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../../JEDEC_security_HAL/crypto_wrapper.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/gcm.h"
|
||||
#include "mbedtls/ccm.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/hkdf.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "../../../spi_nor_flash/spi_nor.h"
|
||||
|
||||
#define KEY_SIZE ((256 / 8) * 2 + 1)
|
||||
#define KEY_MAX_NUM 0x20
|
||||
#define KEY_UNUSED 0
|
||||
#define KEY_USED 1
|
||||
|
||||
#define KEY_HANDLE_NOT_LOADED 0
|
||||
#define MAC_SIZE 0x20
|
||||
#define TAG_LENGTH 0x10
|
||||
|
||||
#define MAX_ROOT_KEY_NUM 0x10
|
||||
#define MAX_SESSION_KEY_NUM 0x10
|
||||
#define MAC_KEY_SIZE 0x20
|
||||
#define ENC_KEY_SIZE 0x10
|
||||
|
||||
#define KEY_ID_LEN 4
|
||||
|
||||
typedef struct {
|
||||
uint8_t value[KEY_SIZE];
|
||||
uint32_t id;
|
||||
uint8_t used:1,
|
||||
len:7;
|
||||
} key_manager_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t enc_key_id;
|
||||
uint32_t mac_key_id;
|
||||
} session_key_id_t;
|
||||
|
||||
static session_key_id_t session_key_id_slot[MAX_SESSION_KEY_NUM] = {};
|
||||
static key_manager_t key_manager[KEY_MAX_NUM] = {};
|
||||
|
||||
/**
|
||||
* \brief Find an empty session key slot.
|
||||
*
|
||||
* \param[out] slot_index Returned empty slot index
|
||||
*
|
||||
* \return true if an empty session key slot was found,
|
||||
* or false there's no empty session key slot
|
||||
*/
|
||||
static bool find_empty_session_key_id_slot(uint32_t *slot_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_SESSION_KEY_NUM; i++) {
|
||||
if ((session_key_id_slot[i].enc_key_id == KEY_HANDLE_NOT_LOADED) &&
|
||||
(session_key_id_slot[i].mac_key_id == KEY_HANDLE_NOT_LOADED)) {
|
||||
*slot_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find the session key slot index corresponding to session key id.
|
||||
* \param[in] session_key_id Input session key id
|
||||
* \param[out] slot_index Returned empty slot index
|
||||
*
|
||||
* \return true if corresponding session key slot was found,
|
||||
* or false there's no matching session key slot
|
||||
*/
|
||||
static bool find_session_key_id_slot(uint32_t session_key_id, uint32_t *slot_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_SESSION_KEY_NUM; i++) {
|
||||
if ((uint32_t)&session_key_id_slot[i] == session_key_id) {
|
||||
*slot_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mbedtls_if_init()
|
||||
{
|
||||
memset(key_manager, 0x00, sizeof(key_manager));
|
||||
memset(session_key_id_slot, 0x00, sizeof(session_key_id_slot));
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int mbedtls_if_deinit()
|
||||
{
|
||||
memset(key_manager, 0x00, sizeof(key_manager));
|
||||
memset(session_key_id_slot, 0x00, sizeof(session_key_id_slot));
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int mbedtls_if_generate_random(uint8_t *odata, uint32_t odata_len)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE;
|
||||
mbedtls_entropy_context entropy_ctx;
|
||||
mbedtls_ctr_drbg_context ctr_drbg_ctx;
|
||||
|
||||
mbedtls_entropy_init(&entropy_ctx);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
|
||||
|
||||
if (0 != mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx, NULL, 0)) {
|
||||
status = JEDEC_ERROR_GENERATE_RANDOM;
|
||||
goto generate_random_exit_point;
|
||||
}
|
||||
|
||||
if (0 != mbedtls_ctr_drbg_random(&ctr_drbg_ctx, odata, odata_len)) {
|
||||
status = JEDEC_ERROR_GENERATE_RANDOM;
|
||||
goto generate_random_exit_point;
|
||||
}
|
||||
|
||||
generate_random_exit_point:
|
||||
mbedtls_entropy_free(&entropy_ctx);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int simple_import_key(uint32_t *key_id, const uint8_t *key, uint8_t key_len)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE;
|
||||
|
||||
if (0 == *key_id) {
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
status = mbedtls_if_generate_random((uint8_t *)key_id, KEY_ID_LEN);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
for (i = 0; i < KEY_MAX_NUM; i++) {
|
||||
if (KEY_USED == key_manager[i].used && *key_id == key_manager[i].id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}while (KEY_MAX_NUM != i);
|
||||
}
|
||||
for (uint8_t i = 0; i < KEY_MAX_NUM; i++) {
|
||||
if (KEY_USED == key_manager[i].used && *key_id == key_manager[i].id) {
|
||||
if (!memcmp(key, key_manager[i].value, key_manager[i].len)) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
return JEDEC_ERROR_KEY_ID_CONFLICT;
|
||||
}
|
||||
if (KEY_UNUSED == key_manager[i].used) {
|
||||
memcpy(key_manager[i].value, key, key_len);
|
||||
key_manager[i].id = *key_id;
|
||||
key_manager[i].len = key_len;
|
||||
key_manager[i].used = KEY_USED;
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return JEDEC_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
|
||||
static int simple_export_key(uint32_t key_id, const uint8_t *key, uint8_t key_len, uint8_t *actual_key_len)
|
||||
{
|
||||
for (uint8_t i = 0; i < KEY_MAX_NUM; i++) {
|
||||
if (KEY_USED == key_manager[i].used && key_id == key_manager[i].id) {
|
||||
if (key_len < key_manager[i].len) {
|
||||
return JEDEC_ERROR_EXPORT_KEY;
|
||||
}
|
||||
memcpy(key, key_manager[i].value, key_manager[i].len);
|
||||
*actual_key_len = key_manager[i].len;
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return JEDEC_ERROR_EXPORT_KEY;
|
||||
}
|
||||
|
||||
static int simple_destroy_key(uint32_t key_id)
|
||||
{
|
||||
uint32_t index, target_key_id;
|
||||
|
||||
if (true == find_session_key_id_slot(key_id, &index)) {
|
||||
target_key_id = session_key_id_slot[index].mac_key_id;
|
||||
|
||||
for (uint8_t i = 0; i < KEY_MAX_NUM; i++) {
|
||||
if (target_key_id == key_manager[i].id) {
|
||||
memset(&key_manager[i], 0x00, sizeof(key_manager_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
target_key_id = session_key_id_slot[index].enc_key_id;
|
||||
|
||||
for (uint8_t i = 0; i < KEY_MAX_NUM; i++) {
|
||||
if (target_key_id == key_manager[i].id) {
|
||||
memset(&key_manager[i], 0x00, sizeof(key_manager_t));
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(&session_key_id_slot[index], 0x00, sizeof(session_key_id_t));
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
for (uint8_t i = 0; i < KEY_MAX_NUM; i++) {
|
||||
if (key_id == key_manager[i].id) {
|
||||
memset(&key_manager[i], 0x00, sizeof(key_manager_t));
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return JEDEC_ERROR_KEY_ID_NOT_FOUND;
|
||||
}
|
||||
|
||||
static int simple_open_key(uint32_t key_id)
|
||||
{
|
||||
(void)key_id;
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int simple_close_key(uint32_t key_id)
|
||||
{
|
||||
(void)key_id;
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int mbedtls_if_aes_gcm(crypto_indicator_t *indicator)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE, mbedl_status, index;
|
||||
mbedtls_gcm_context ctx = {};
|
||||
uint8_t key[16];
|
||||
uint8_t actual_key_len = 0;
|
||||
|
||||
mbedtls_gcm_init(&ctx);
|
||||
|
||||
/* export key from session key slot or key manager */
|
||||
bool ret = find_session_key_id_slot(indicator->aead.key_id, &index);
|
||||
if (true == ret) {
|
||||
status = simple_export_key(session_key_id_slot[index].enc_key_id, key, indicator->aead.key_len, &actual_key_len);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
goto aes_gcm_exit_point;
|
||||
}
|
||||
} else {
|
||||
status = simple_export_key(indicator->aead.key_id, key, indicator->aead.key_len, &actual_key_len);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
goto aes_gcm_exit_point;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != mbedtls_gcm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, indicator->aead.key_len * 8)) {
|
||||
status = JEDEC_ERROR_AEAD;
|
||||
goto aes_gcm_exit_point;
|
||||
}
|
||||
switch (indicator->property) {
|
||||
case PROP_AUTHEN_TAG_DECRYPT_DATA:
|
||||
case PROP_AUTHEN_TAG:
|
||||
mbedl_status = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_DECRYPT,
|
||||
indicator->aead.text_len,
|
||||
indicator->aead.iv, indicator->aead.iv_len,
|
||||
indicator->aead.add, indicator->aead.add_len,
|
||||
indicator->aead.cipher_text, indicator->aead.plain_text,
|
||||
indicator->aead.tag_len, indicator->aead.tag);
|
||||
if (0 != mbedl_status) {
|
||||
status = JEDEC_ERROR_AEAD;
|
||||
goto aes_gcm_exit_point;
|
||||
}
|
||||
break;
|
||||
case PROP_ENCRYPT_TAG_DATA:
|
||||
case PROP_ENCRYPT_TAG:
|
||||
mbedl_status = mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT,
|
||||
indicator->aead.text_len,
|
||||
indicator->aead.iv, indicator->aead.iv_len,
|
||||
indicator->aead.add, indicator->aead.add_len,
|
||||
indicator->aead.plain_text, indicator->aead.cipher_text,
|
||||
indicator->aead.tag_len, indicator->aead.tag);
|
||||
if (0 != mbedl_status) {
|
||||
status = JEDEC_ERROR_AEAD;
|
||||
goto aes_gcm_exit_point;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = JEDEC_ERROR_AEAD;
|
||||
goto aes_gcm_exit_point;
|
||||
}
|
||||
aes_gcm_exit_point:
|
||||
mbedtls_gcm_free(&ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
static mbedtls_md_type_t sha_select_md_type(CryptoAlgorithm alg)
|
||||
{
|
||||
switch (alg) {
|
||||
case ALG_HKDF_SHA_1:
|
||||
case ALG_HMAC_SHA_1:
|
||||
return MBEDTLS_MD_SHA1;
|
||||
case ALG_HKDF_SHA_224:
|
||||
case ALG_HMAC_SHA_224:
|
||||
return MBEDTLS_MD_SHA224;
|
||||
case ALG_HKDF_SHA_256:
|
||||
case ALG_HMAC_SHA_256:
|
||||
return MBEDTLS_MD_SHA256;
|
||||
case ALG_HKDF_SHA_384:
|
||||
case ALG_HMAC_SHA_384:
|
||||
return MBEDTLS_MD_SHA384;
|
||||
case ALG_HKDF_SHA_512:
|
||||
case ALG_HMAC_SHA_512:
|
||||
return MBEDTLS_MD_SHA512;
|
||||
default:
|
||||
return MBEDTLS_MD_NONE;
|
||||
}
|
||||
return MBEDTLS_MD_NONE;
|
||||
}
|
||||
|
||||
static mbedtls_ecp_group_id ecdh_select_grp(CryptoAlgorithm alg)
|
||||
{
|
||||
switch (alg) {
|
||||
case ALG_ECDH_SECP192R1:
|
||||
return MBEDTLS_ECP_DP_SECP192R1;
|
||||
case ALG_ECDH_SECP224R1:
|
||||
return MBEDTLS_ECP_DP_SECP224R1;
|
||||
case ALG_ECDH_SECP256R1:
|
||||
return MBEDTLS_ECP_DP_SECP256R1;
|
||||
case ALG_ECDH_SECP384R1:
|
||||
return MBEDTLS_ECP_DP_SECP384R1;
|
||||
// case ALG_ECDH_SECP521R1:
|
||||
// return MBEDTLS_ECP_DP_SECP521R1;
|
||||
case ALG_ECDH_BP256R1:
|
||||
return MBEDTLS_ECP_DP_BP256R1;
|
||||
case ALG_ECDH_BP384R1:
|
||||
return MBEDTLS_ECP_DP_BP384R1;
|
||||
// case ALG_ECDH_BP512R1:
|
||||
// return MBEDTLS_ECP_DP_BP512R1;
|
||||
case ALG_ECDH_CURVE25519:
|
||||
return MBEDTLS_ECP_DP_CURVE25519;
|
||||
case ALG_ECDH_SECP192K1:
|
||||
return MBEDTLS_ECP_DP_SECP192K1;
|
||||
case ALG_ECDH_SECP224K1:
|
||||
return MBEDTLS_ECP_DP_SECP224K1;
|
||||
case ALG_ECDH_SECP256K1:
|
||||
return MBEDTLS_ECP_DP_SECP256K1;
|
||||
default:
|
||||
return MBEDTLS_ECP_DP_NONE;
|
||||
}
|
||||
return MBEDTLS_ECP_DP_NONE;
|
||||
}
|
||||
|
||||
static int mbedtls_if_ecdh_gen_key_pair(crypto_indicator_t *indicator)
|
||||
{
|
||||
/* The procedure refer to the Mbedtls's test suite (test_suite_ecdh.c) */
|
||||
int32_t status = JEDEC_ERROR_NONE;
|
||||
size_t olen;
|
||||
uint8_t pri_key[(256/8)+1] = {}, pub_key[(512/8)+1] ={};
|
||||
mbedtls_ecp_group_id ecp_grp_id;
|
||||
mbedtls_mpi host_pri;
|
||||
mbedtls_ecp_group grp;
|
||||
mbedtls_ecp_point host_pub;
|
||||
mbedtls_entropy_context entropy_ctx;
|
||||
mbedtls_ctr_drbg_context ctr_drbg_ctx;
|
||||
|
||||
/* Init. data struct */
|
||||
mbedtls_mpi_init(&host_pri);
|
||||
mbedtls_ecp_group_init(&grp);
|
||||
mbedtls_ecp_point_init(&host_pub);
|
||||
mbedtls_entropy_init(&entropy_ctx);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
|
||||
/* Update random seed use custom string(pers) */
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx, NULL, 0);
|
||||
ecp_grp_id = ecdh_select_grp(indicator->algorithm);
|
||||
if (ecp_grp_id == MBEDTLS_ECP_DP_NONE) {
|
||||
status = JEDEC_ERROR_NOT_SUPPORT;
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
mbedtls_ecp_group_load(&grp, ecp_grp_id);
|
||||
/* Generate an ECDH key pair on an elliptic curve, private key in host_pri and public key in host_pub */
|
||||
mbedtls_ecdh_gen_public(&grp, &host_pri, &host_pub, mbedtls_ctr_drbg_random, &ctr_drbg_ctx);
|
||||
/* Derived public key */
|
||||
switch (indicator->ecdh.pub_key_type) {
|
||||
case RAW_PUB_KEY:
|
||||
mbedtls_ecp_point_write_binary(&grp, &host_pub, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen,
|
||||
pub_key, indicator->ecdh.pub_key_len + 1);
|
||||
memmove(pub_key, &pub_key[1], olen - 1);
|
||||
if(indicator->ecdh.pub_key_len != (olen - 1)) {
|
||||
status = JEDEC_ERROR_INV_ARGS;
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
break;
|
||||
case UNCOMPRESSED_PUB_KEY:
|
||||
mbedtls_ecp_point_write_binary(&grp, &host_pub, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen,
|
||||
pub_key, indicator->ecdh.pub_key_len);
|
||||
if(indicator->ecdh.pub_key_len != olen) {
|
||||
status = JEDEC_ERROR_INV_ARGS;
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
break;
|
||||
case COMPRESSED_PUB_KEY:
|
||||
mbedtls_ecp_point_write_binary(&grp, &host_pub, MBEDTLS_ECP_PF_COMPRESSED, &olen,
|
||||
pub_key, indicator->ecdh.pub_key_len);
|
||||
if(indicator->ecdh.pub_key_len != olen) {
|
||||
status = JEDEC_ERROR_INV_ARGS;
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = JEDEC_ERROR_NOT_SUPPORT;
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
memcpy(indicator->ecdh.pub_key, pub_key, indicator->ecdh.pub_key_len);
|
||||
indicator->ecdh.pri_key_len = mbedtls_mpi_size(&host_pri);
|
||||
|
||||
/* Derived private key */
|
||||
mbedtls_mpi_write_binary(&host_pri, pri_key, mbedtls_mpi_size(&host_pri));
|
||||
status = simple_import_key(&indicator->ecdh.pub_key_id, indicator->ecdh.pub_key, indicator->ecdh.pub_key_len);
|
||||
if (status != JEDEC_ERROR_NONE) {
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
status = simple_import_key(&indicator->ecdh.pri_key_id, pri_key, indicator->ecdh.pri_key_len);
|
||||
if (status != JEDEC_ERROR_NONE) {
|
||||
goto mbedtls_if_ecdh_gen_key_pair_exit_point;
|
||||
}
|
||||
memset(pri_key, 0x00, sizeof(pri_key));
|
||||
mbedtls_if_ecdh_gen_key_pair_exit_point:
|
||||
mbedtls_mpi_free(&host_pri);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
mbedtls_ecp_point_free(&host_pub);
|
||||
mbedtls_entropy_free(&entropy_ctx);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int32_t mbedlts_if_ecdh_gen_shared_secret(crypto_indicator_t *indicator)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE;
|
||||
const char *pers = "mbedtls_ecdh";
|
||||
mbedtls_mpi host_secret;
|
||||
mbedtls_mpi host_pri;
|
||||
mbedtls_ecp_group grp;
|
||||
mbedtls_ecp_point dev_pub;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ecp_group_id ecp_grp_id;
|
||||
uint8_t host_pri_key[256 / 8 +1] = {};
|
||||
uint8_t secret[256 / 8] = {};
|
||||
uint8_t actual_key_len;
|
||||
uint8_t pub_key_half_len, ofs = 0;
|
||||
|
||||
if (NULL == indicator->ecdh.secret && !indicator->key_attr.import_req) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
/* Init. data struct */
|
||||
mbedtls_mpi_init(&host_secret);
|
||||
mbedtls_mpi_init(&host_pri);
|
||||
mbedtls_ecp_group_init(&grp);
|
||||
mbedtls_ecp_point_init(&dev_pub);
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
|
||||
/* Update random seed use custom string(pers) */
|
||||
// mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const uint8_t *)pers, strlen(pers));
|
||||
mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
|
||||
ecp_grp_id = ecdh_select_grp(indicator->algorithm);
|
||||
if (ecp_grp_id == MBEDTLS_ECP_DP_NONE) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
mbedtls_ecp_group_load(&grp, ecp_grp_id);
|
||||
status = simple_export_key(indicator->ecdh.pri_key_id, host_pri_key, sizeof(host_pri_key), &actual_key_len);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
switch (indicator->ecdh.pub_key_type) {
|
||||
case RAW_PUB_KEY:
|
||||
pub_key_half_len = indicator->ecdh.pub_key_len / 2;
|
||||
ofs = 0;
|
||||
break;
|
||||
case UNCOMPRESSED_PUB_KEY:
|
||||
pub_key_half_len = (indicator->ecdh.pub_key_len - 1) / 2;
|
||||
ofs = 1;
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
/* Import device public key to dev_pub */
|
||||
mbedtls_mpi_read_binary(&dev_pub.X, indicator->ecdh.pub_key + ofs, pub_key_half_len);
|
||||
mbedtls_mpi_read_binary(&dev_pub.Y, indicator->ecdh.pub_key + ofs + pub_key_half_len, pub_key_half_len);
|
||||
mbedtls_mpi_lset(&dev_pub.Z, 1);
|
||||
|
||||
/* Import host private key to host_pri */
|
||||
mbedtls_mpi_read_binary(&host_pri, host_pri_key, indicator->ecdh.pri_key_len);
|
||||
|
||||
/* Compute the shared secret */
|
||||
mbedtls_ecdh_compute_shared(&grp, &host_secret, &dev_pub, &host_pri, mbedtls_ctr_drbg_random, &ctr_drbg);
|
||||
|
||||
/* Derived shared secret */
|
||||
mbedtls_mpi_write_binary(&host_secret, secret, mbedtls_mpi_size(&host_secret));
|
||||
indicator->ecdh.secret_len = mbedtls_mpi_size(&host_secret);
|
||||
|
||||
if (indicator->key_attr.import_req) {
|
||||
status = simple_import_key(&indicator->ecdh.secret_id, secret, indicator->ecdh.secret_len);
|
||||
if (status != JEDEC_ERROR_NONE) {
|
||||
return JEDEC_ERROR_GENERATE_KEY;
|
||||
}
|
||||
memset(secret, 0x00, indicator->ecdh.secret_len);
|
||||
} else {
|
||||
memcpy(indicator->ecdh.secret, secret, indicator->ecdh.secret_len);
|
||||
}
|
||||
|
||||
mbedtls_mpi_free(&host_pri);
|
||||
mbedtls_mpi_free(&host_secret);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
mbedtls_ecp_point_free(&dev_pub);
|
||||
mbedtls_entropy_free(&entropy);
|
||||
mbedtls_ctr_drbg_free(&ctr_drbg);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mbedtls_if_hmac_compute(crypto_indicator_t *indicator, mbedtls_md_info_t *md, uint8_t *key)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE;
|
||||
uint8_t mac[256 / 8] = {};
|
||||
|
||||
if (0 != mbedtls_md_hmac(md, key, indicator->hmac.key_len, indicator->hmac.idata, indicator->hmac.idata_len, mac)) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
if (indicator->key_attr.import_req) {
|
||||
status = simple_import_key(&indicator->hmac.mac_id, mac, indicator->hmac.key_len);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
memset (mac, 0x00, indicator->hmac.mac_len);
|
||||
} else {
|
||||
memcpy(indicator->hmac.mac, mac, indicator->hmac.mac_len);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mbedtls_if_hmac_verify(crypto_indicator_t *indicator, mbedtls_md_info_t *md, uint8_t *key)
|
||||
{
|
||||
uint8_t mac[256 / 8] = {};
|
||||
|
||||
if (0 != mbedtls_md_hmac(md,
|
||||
key,
|
||||
indicator->hmac.key_len,
|
||||
indicator->hmac.idata,
|
||||
indicator->hmac.idata_len,
|
||||
mac)) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
if (memcmp(mac, indicator->hmac.mac, indicator->hmac.mac_len)) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int mbedtls_if_hmac(crypto_indicator_t *indicator)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE;
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
|
||||
mbedtls_md_info_t *md = NULL;
|
||||
uint8_t key[256 / 8], actual_key_len = 0;
|
||||
|
||||
if ((0 == indicator->hmac.key_id && NULL == indicator->hmac.key) ||
|
||||
NULL == indicator->hmac.idata || 0 == indicator->hmac.idata_len) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (PROP_HMAC_VERIFY == indicator->property && NULL == indicator->hmac.mac) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (NULL == indicator->hmac.mac && 0 == indicator->key_attr.import_req) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (ALG_HMAC != ALG_TYPE(indicator->algorithm)) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
md_type = sha_select_md_type(indicator->algorithm);
|
||||
if (MBEDTLS_MD_NONE == md_type) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
md = mbedtls_md_info_from_type(md_type);
|
||||
if (NULL == md) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
if (indicator->hmac.mac_len != mbedtls_md_get_size(md)) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
/* If hmac.key is NULL, then export key from session key slot or key manager */
|
||||
if (NULL == indicator->hmac.key) {
|
||||
int index;
|
||||
bool ret = find_session_key_id_slot(indicator->hmac.key_id, & index);
|
||||
if (true == ret) {
|
||||
status = simple_export_key(session_key_id_slot[index].mac_key_id, key, indicator->hmac.key_len, &actual_key_len);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
status = simple_export_key(indicator->hmac.key_id, key, indicator->hmac.key_len, &actual_key_len);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memcpy(key , indicator->hmac.key, indicator->hmac.key_len);
|
||||
}
|
||||
|
||||
switch (indicator->property) {
|
||||
case PROP_HMAC_COMPUTE:
|
||||
status = mbedtls_if_hmac_compute(indicator, md, key);
|
||||
break;
|
||||
case PROP_HMAC_VERIFY:
|
||||
status = mbedtls_if_hmac_verify(indicator, md, key);
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int mbedtls_if_mx78_kdf(crypto_indicator_t *indicator)
|
||||
{
|
||||
int status = JEDEC_ERROR_NONE, index = 0;
|
||||
uint8_t actual_key_len = 0, prk[256 / 8], okm[256 / 8];
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
|
||||
mbedtls_md_info_t *md = NULL;
|
||||
|
||||
if (true != find_empty_session_key_id_slot(&index)) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
md_type = sha_select_md_type(indicator->algorithm);
|
||||
if (MBEDTLS_MD_NONE == md_type) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
md = mbedtls_md_info_from_type(md_type);
|
||||
if (NULL == md) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
if (indicator->hkdf.prk_len != mbedtls_md_get_size(md)) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (NULL == indicator->hkdf.prk) {
|
||||
status = simple_export_key(indicator->hkdf.prk_id, prk, indicator->hkdf.prk_len, &actual_key_len);
|
||||
if (status != JEDEC_ERROR_NONE) {
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
memcpy(prk, indicator->hkdf.prk, indicator->hkdf.prk_len);
|
||||
}
|
||||
if (0 != mbedtls_md_hmac(md, prk, indicator->hkdf.prk_len, indicator->hkdf.info, indicator->hkdf.info_len, okm)) {
|
||||
return JEDEC_ERROR_KDF;
|
||||
}
|
||||
/* import mac and enc key */
|
||||
status = simple_import_key(&session_key_id_slot[index].mac_key_id, okm, MAC_KEY_SIZE);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
status = simple_import_key(&session_key_id_slot[index].enc_key_id, okm, ENC_KEY_SIZE);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
memset(okm, 0x00, mbedtls_md_get_size(md));
|
||||
memset(prk, 0x00, mbedtls_md_get_size(md));
|
||||
indicator->hkdf.okm_id = (uint32_t)&session_key_id_slot[index];
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
const static crypto_func_t CRYPTO_FUNC[] = {
|
||||
0, //ALG_NONE 0
|
||||
0, //ALG_AES_CCM 1
|
||||
mbedtls_if_aes_gcm, //ALG_AES_GCM 2
|
||||
0, //ALG_AES_ECB 3
|
||||
0, //ALG_AES_CBC 4
|
||||
0, //ALG_AES_OFB 5
|
||||
0, //ALG_AES_CTR 6
|
||||
0, //ALG_ECDSA 7
|
||||
0, //ALG_ECDH 8
|
||||
mbedtls_if_hmac, //ALG_HMAC 9
|
||||
mbedtls_if_mx78_kdf, //ALG_HKDF 10
|
||||
};
|
||||
|
||||
static int mbedtls_if_algorithm_support(int alg, int index)
|
||||
{
|
||||
if (ALG_NONE == alg) {
|
||||
return JEDEC_ERROR_NOTHING;
|
||||
}
|
||||
if ((sizeof(CRYPTO_FUNC)/sizeof(crypto_func_t)) <= index || 0 == CRYPTO_FUNC[index]) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int mbedtls_if_crypto_func(crypto_indicator_t *indicator)
|
||||
{
|
||||
int status = JEDEC_ERROR_NONE, index = ALG_TYPE(indicator->algorithm) >> 4;
|
||||
|
||||
status = mbedtls_if_algorithm_support(indicator->algorithm, index);
|
||||
if (JEDEC_ERROR_NOTHING == status) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
return CRYPTO_FUNC[index](indicator);
|
||||
}
|
||||
|
||||
static int mbedtls_if_key_derive(crypto_indicator_t *indicator, uint32_t *output_key_id)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE, index = ALG_TYPE(indicator->algorithm) >> 4;
|
||||
|
||||
status = mbedtls_if_algorithm_support(indicator->algorithm, index);
|
||||
if (JEDEC_ERROR_NOTHING == status) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
status = CRYPTO_FUNC[index](indicator);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return JEDEC_ERROR_KDF;
|
||||
}
|
||||
switch (ALG_TYPE(indicator->algorithm)) {
|
||||
case ALG_HKDF:
|
||||
*output_key_id = indicator->hkdf.okm_id;
|
||||
break;
|
||||
case ALG_HMAC:
|
||||
*output_key_id = indicator->hmac.mac_id;
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
|
||||
}
|
||||
|
||||
const crypto_wrapper_t mx78_armor_crypto_wrapper = {
|
||||
.init = mbedtls_if_init,
|
||||
.deinit = mbedtls_if_deinit,
|
||||
.algorithm_support = mbedtls_if_algorithm_support,
|
||||
.crypto_func = mbedtls_if_crypto_func,
|
||||
.key_derive = mbedtls_if_key_derive,
|
||||
.generate_random = mbedtls_if_generate_random,
|
||||
.ecdh_gen_key_pair = mbedtls_if_ecdh_gen_key_pair,
|
||||
.ecdh_gen_shared_secret = mbedlts_if_ecdh_gen_shared_secret,
|
||||
.open_key = simple_open_key,
|
||||
.close_key = simple_close_key,
|
||||
.destroy_key = simple_destroy_key,
|
||||
.export_key = simple_export_key,
|
||||
.import_key = simple_import_key
|
||||
};
|
||||
#endif /* CRYPTO_MBEDTLS */
|
|
@ -0,0 +1,742 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
|
||||
#ifdef CRYPTO_PSA
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "../../../../JEDEC_security_HAL/crypto_wrapper.h"
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#define KEY_HANDLE_NOT_LOADED (0)
|
||||
#define MAC_SIZE (0x20)
|
||||
#define TAG_LENGTH (0x10)
|
||||
|
||||
#define MAX_ROOT_KEY_NUM (0x10)
|
||||
#define MAX_SESSION_KEY_NUM (0x10)
|
||||
#define MAC_KEY_SIZE (0x20)
|
||||
#define ENC_KEY_SIZE (0x10)
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t session_enc_key_id;
|
||||
uint32_t session_mac_key_id;
|
||||
} session_key_id_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t root_key_id;
|
||||
uint32_t root_key_handle;
|
||||
} root_key_handle_t;
|
||||
|
||||
static session_key_id_t session_key_id_slot[MAX_SESSION_KEY_NUM] = {KEY_HANDLE_NOT_LOADED};
|
||||
static root_key_handle_t root_key_slot[MAX_ROOT_KEY_NUM] = {KEY_HANDLE_NOT_LOADED};
|
||||
|
||||
/**
|
||||
* \brief Find an empty session key slot.
|
||||
*
|
||||
* \param[out] slot_index Returned empty slot index
|
||||
*
|
||||
* \return true if an empty session key slot was found,
|
||||
* or false there's no empty session key slot
|
||||
*/
|
||||
static bool find_empty_session_key_id_slot(uint32_t *slot_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_SESSION_KEY_NUM; i++) {
|
||||
if ((session_key_id_slot[i].session_enc_key_id == KEY_HANDLE_NOT_LOADED) &&
|
||||
(session_key_id_slot[i].session_mac_key_id == KEY_HANDLE_NOT_LOADED)) {
|
||||
*slot_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find the session key slot index corresponding to session key id.
|
||||
* \param[in] session_key_id Input session key id
|
||||
* \param[out] slot_index Returned empty slot index
|
||||
*
|
||||
* \return true if corresponding session key slot was found,
|
||||
* or false there's no matching session key slot
|
||||
*/
|
||||
static bool find_session_key_id_slot(uint32_t session_key_id, uint32_t *slot_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_SESSION_KEY_NUM; i++) {
|
||||
if ((uint32_t)&session_key_id_slot[i] == session_key_id) {
|
||||
*slot_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find an empty root key slot.
|
||||
*
|
||||
* \param[out] slot_index Returned empty slot index
|
||||
*
|
||||
* \return true if an empty root key slot was found,
|
||||
* or false there's no empty root key slot
|
||||
*/
|
||||
static bool find_empty_root_key_id_slot(uint32_t *slot_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_ROOT_KEY_NUM; i++) {
|
||||
if ((root_key_slot[i].root_key_handle == KEY_HANDLE_NOT_LOADED) &&
|
||||
(root_key_slot[i].root_key_id == KEY_HANDLE_NOT_LOADED)) {
|
||||
*slot_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find the root key slot index corresponding to root key id.
|
||||
* \param[in] root_key_id Input root key id
|
||||
* \param[out] slot_index Returned empty slot index
|
||||
*
|
||||
* \return true if corresponding session key slot was found,
|
||||
* or false there's no matching session key slot
|
||||
*/
|
||||
static bool find_root_key_id_slot(uint32_t root_key_id, uint32_t *slot_index)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_ROOT_KEY_NUM; i++) {
|
||||
if (root_key_slot[i].root_key_id == root_key_id) {
|
||||
*slot_index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_init(void)
|
||||
{
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_deinit(void)
|
||||
{
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_mx78_kdf(crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint8_t mac[MAC_SIZE];
|
||||
size_t mac_length;
|
||||
uint32_t vol_root_key_id;
|
||||
uint32_t index;
|
||||
/* session_key_id ==> {
|
||||
* session_enc_key_id,
|
||||
* session_mac_key_id
|
||||
* }
|
||||
*/
|
||||
if (true == find_empty_session_key_id_slot(&index)) {
|
||||
indicator->hkdf.okm_id = (uint32_t)&session_key_id_slot[index];
|
||||
} else {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
/* Open root key to tf-m crypto key slot */
|
||||
status = psa_open_key(indicator->hkdf.prk_id, &vol_root_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_OPEN_KEY;
|
||||
}
|
||||
/* Multi-part mac compute */
|
||||
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
|
||||
status = psa_mac_sign_setup(&operation,
|
||||
vol_root_key_id,
|
||||
PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
status = psa_mac_update(&operation,
|
||||
indicator->hkdf.info,
|
||||
indicator->hkdf.info_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
status = psa_mac_sign_finish(&operation, mac, MAC_SIZE, &mac_length);
|
||||
if ((status != PSA_SUCCESS) ||
|
||||
(mac_length != MAC_SIZE)) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
/* import volatile hmac key */
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
|
||||
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
|
||||
psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(MAC_KEY_SIZE));
|
||||
status = psa_import_key(&attributes,
|
||||
mac, MAC_KEY_SIZE,
|
||||
&(session_key_id_slot[index].session_mac_key_id));
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_IMPORT_KEY;
|
||||
}
|
||||
/* import volatile aes-gcm key */
|
||||
memset(&attributes, 0x00, sizeof(attributes));
|
||||
psa_set_key_usage_flags(&attributes,
|
||||
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
|
||||
psa_set_key_algorithm(&attributes,
|
||||
PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, TAG_LENGTH));
|
||||
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(ENC_KEY_SIZE));
|
||||
status = psa_import_key(&attributes,
|
||||
mac, ENC_KEY_SIZE,
|
||||
&(session_key_id_slot[index].session_enc_key_id));
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_IMPORT_KEY;
|
||||
}
|
||||
/* Close root key handle from tf-m crypto key slot */
|
||||
status = psa_close_key(vol_root_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_CLOSE_KEY;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_ecdh_gen_key_pair(crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint16_t key_bits;
|
||||
size_t exported_length = 0;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
/* Generate an ECC key pair */
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
|
||||
psa_set_key_algorithm(&attributes, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, 0x00));
|
||||
switch (indicator->algorithm) {
|
||||
case ALG_ECDH_SECP192R1:
|
||||
case ALG_ECDH_SECP224R1:
|
||||
case ALG_ECDH_SECP256R1:
|
||||
case ALG_ECDH_SECP384R1:
|
||||
psa_set_key_type(&attributes,
|
||||
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
break;
|
||||
case ALG_ECDH_BP256R1:
|
||||
case ALG_ECDH_BP384R1:
|
||||
psa_set_key_type(&attributes,
|
||||
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1));
|
||||
break;
|
||||
case ALG_ECDH_SECP192K1:;
|
||||
case ALG_ECDH_SECP256K1:
|
||||
psa_set_key_type(&attributes,
|
||||
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1));
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
key_bits = 8 * indicator->ecdh.pri_key_len;
|
||||
psa_set_key_bits(&attributes, key_bits);
|
||||
status = psa_generate_key(&attributes, &indicator->ecdh.pri_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_GENERATE_KEY;
|
||||
}
|
||||
indicator->ecdh.pub_key_id = indicator->ecdh.pri_key_id;
|
||||
status = psa_export_public_key(indicator->ecdh.pub_key_id,
|
||||
indicator->ecdh.pub_key,
|
||||
indicator->ecdh.pub_key_len,
|
||||
&exported_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_EXPORT_KEY;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_ecdh_gen_shared_secret(crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint32_t actual_size;
|
||||
status = psa_raw_key_agreement(PSA_ALG_ECDH,
|
||||
indicator->ecdh.pri_key_id,
|
||||
indicator->ecdh.pub_key,
|
||||
indicator->ecdh.pub_key_len,
|
||||
indicator->ecdh.secret,
|
||||
indicator->ecdh.secret_len,
|
||||
&actual_size);
|
||||
if (status) {
|
||||
return JEDEC_ERROR_GENERATE_KEY;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Open root key corresponding to root_key_id.
|
||||
* \param[in] root_key_id Input root key id
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_open_key(uint32_t root_key_id)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint32_t key_handle;
|
||||
uint32_t index;
|
||||
|
||||
status = psa_open_key(root_key_id, &key_handle);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_OPEN_KEY;
|
||||
}
|
||||
if (find_empty_root_key_id_slot(&index) == true) {
|
||||
root_key_slot[index].root_key_id = root_key_id;
|
||||
root_key_slot[index].root_key_handle = key_handle;
|
||||
} else {
|
||||
return JEDEC_ERROR_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Close root key corresponding to root_key_id.
|
||||
* \param[in] root_key_id Input root key id
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_close_key(uint32_t root_key_id)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint32_t index;
|
||||
|
||||
if (find_root_key_id_slot(root_key_id, &index) == true) {
|
||||
status = psa_close_key(root_key_slot[index].root_key_handle);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_CLOSE_KEY;
|
||||
}
|
||||
root_key_slot[index].root_key_handle = KEY_HANDLE_NOT_LOADED;
|
||||
root_key_slot[index].root_key_id = KEY_HANDLE_NOT_LOADED;
|
||||
} else {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_export_public_key(uint32_t key_id, uint8_t *key_buf,
|
||||
uint32_t buf_size, uint32_t *actual_size)
|
||||
{
|
||||
psa_status_t status;
|
||||
status = psa_export_public_key(key_id, key_buf, buf_size,
|
||||
actual_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_export_key(uint32_t key_id, uint8_t *key_buf,
|
||||
uint32_t buf_size, uint32_t *actual_size)
|
||||
{
|
||||
psa_status_t status;
|
||||
status = psa_export_key(key_id, key_buf, buf_size,
|
||||
actual_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_import_key(uint32_t *key_id, uint8_t *key_buf,
|
||||
uint32_t key_size, KeyLifeTime lifetime)
|
||||
{
|
||||
psa_status_t status;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_SIGN_HASH);
|
||||
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
|
||||
psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(key_size));
|
||||
if (lifetime == KEY_LIFETIME_VOLATILE) {
|
||||
*key_id = PSA_KEY_ID_NULL;
|
||||
} else {
|
||||
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
|
||||
psa_set_key_id(&attributes, *key_id);
|
||||
}
|
||||
status = psa_import_key(&attributes, key_buf, key_size, key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_IMPORT_KEY;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
/**
|
||||
* \brief Destroy session key corresponding to session_key_id.
|
||||
* \param[in] session_key_id Input session key id
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_destroy_key(uint32_t key_id)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint32_t index;
|
||||
|
||||
if (find_session_key_id_slot(key_id, &index) == true) {
|
||||
/* Destroy session's encryption key */
|
||||
status = psa_destroy_key(session_key_id_slot[index].session_enc_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_DESTROY_KEY;
|
||||
}
|
||||
session_key_id_slot[index].session_enc_key_id = KEY_HANDLE_NOT_LOADED;
|
||||
/* Destroy session's hmac key */
|
||||
status = psa_destroy_key(session_key_id_slot[index].session_mac_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_DESTROY_KEY;
|
||||
}
|
||||
session_key_id_slot[index].session_mac_key_id = KEY_HANDLE_NOT_LOADED;
|
||||
} else {
|
||||
status = psa_destroy_key(key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_DESTROY_KEY;
|
||||
}
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_aes_ccm(crypto_indicator_t *indicator)
|
||||
{
|
||||
/* TODO */
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_aes_ecb(crypto_indicator_t *indicator)
|
||||
{
|
||||
/* TODO */
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Implement AEAD encryption with input session_key_id.
|
||||
* \param[in] session_key_id Input session key id
|
||||
* \param[in] indicator AEAD encryption parameters
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_aead_enc(uint32_t session_key_id, crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
size_t out_len;
|
||||
|
||||
if (sizeof(indicator->buf) <
|
||||
PSA_AEAD_ENCRYPT_OUTPUT_SIZE(PSA_KEY_TYPE_AES,
|
||||
PSA_ALG_GCM,
|
||||
indicator->aead.text_len)) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
session_key_id_t *session_key_id_ptr = (session_key_id_t *)session_key_id;
|
||||
status = psa_aead_encrypt((psa_key_id_t)session_key_id_ptr->session_enc_key_id,
|
||||
PSA_ALG_GCM,
|
||||
indicator->aead.iv, indicator->aead.iv_len,
|
||||
indicator->aead.add, indicator->aead.add_len,
|
||||
indicator->aead.plain_text, indicator->aead.text_len,
|
||||
indicator->buf, sizeof(indicator->buf), &out_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_AEAD_ENC;
|
||||
}
|
||||
/* Authentication tag is appended to the encrypted data */
|
||||
/* NOTE:The indicator->aead.cipher_text has been set to point to send packet previously,
|
||||
here just copy the actual mac and ciphertext to send packet */
|
||||
indicator->aead.text_len = out_len -
|
||||
PSA_AEAD_TAG_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_GCM);
|
||||
memcpy(indicator->aead.cipher_text, indicator->buf, indicator->aead.text_len);
|
||||
indicator->aead.tag_len = PSA_AEAD_TAG_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_GCM);
|
||||
memcpy(indicator->aead.tag,
|
||||
indicator->buf + indicator->aead.text_len,
|
||||
indicator->aead.tag_len);
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Implement AEAD decryption with input session_key_id.
|
||||
* \param[in] session_key_id Input session key id
|
||||
* \param[in] indicator AEAD decryption parameters
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_aead_dec(uint32_t session_key_id, crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
size_t out_len;
|
||||
|
||||
session_key_id_t *session_key_id_ptr = (session_key_id_t *)session_key_id;
|
||||
memcpy(indicator->buf, indicator->aead.cipher_text, indicator->aead.text_len);
|
||||
memcpy(indicator->buf + indicator->aead.text_len,
|
||||
indicator->aead.tag, indicator->aead.tag_len);
|
||||
status = psa_aead_decrypt((psa_key_id_t)session_key_id_ptr->session_enc_key_id,
|
||||
PSA_ALG_GCM,
|
||||
indicator->aead.iv, indicator->aead.iv_len,
|
||||
indicator->aead.add, indicator->aead.add_len,
|
||||
indicator->buf,
|
||||
indicator->aead.text_len + indicator->aead.tag_len,
|
||||
indicator->aead.plain_text,
|
||||
indicator->aead.text_len, &out_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_AEAD_DEC;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_aes_gcm(crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
size_t out_len;
|
||||
|
||||
switch (indicator->property) {
|
||||
case PROP_AUTHEN_TAG_DECRYPT_DATA:
|
||||
case PROP_AUTHEN_TAG:
|
||||
return crypto_wrapper_aead_dec(indicator->aead.key_id, indicator);
|
||||
break;
|
||||
case PROP_ENCRYPT_TAG_DATA:
|
||||
case PROP_ENCRYPT_TAG:
|
||||
return crypto_wrapper_aead_enc(indicator->aead.key_id, indicator);
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_AEAD;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compute MAC with input session key.
|
||||
* \param[in] session_key_id Input session key id
|
||||
* \param[in] indicator MAC operation parameters
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_mac_compute(uint32_t key_id, crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
size_t actual_mac_size;
|
||||
uint32_t index;
|
||||
|
||||
/* No need for computing mac */
|
||||
if ((indicator->hmac.idata == NULL) && (indicator->hmac.idata_len == 0)) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
|
||||
|
||||
if (find_session_key_id_slot(key_id, &index) == true) {
|
||||
session_key_id_t *session_key_id_ptr = key_id;
|
||||
status = psa_mac_sign_setup(&operation,
|
||||
session_key_id_ptr->session_mac_key_id,
|
||||
PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
} else {
|
||||
status = psa_mac_sign_setup(&operation,
|
||||
key_id,
|
||||
PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
}
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
status = psa_mac_update(&operation,
|
||||
indicator->hmac.idata,
|
||||
indicator->hmac.idata_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
status = psa_mac_sign_finish(&operation,
|
||||
indicator->hmac.mac,
|
||||
indicator->hmac.mac_len,
|
||||
&actual_mac_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Implement MAC verify with input session key.
|
||||
* \param[in] session_key_id Input session key id
|
||||
* \param[in] indicator MAC verify parameters
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_mac_verify(uint32_t key_id, crypto_indicator_t *indicator)
|
||||
{
|
||||
psa_status_t status;
|
||||
uint32_t index;
|
||||
|
||||
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
|
||||
if (find_session_key_id_slot(key_id, &index) == true) {
|
||||
session_key_id_t *session_key_id_ptr = key_id;
|
||||
status = psa_mac_verify_setup(&operation,
|
||||
session_key_id_ptr->session_mac_key_id,
|
||||
PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
} else {
|
||||
status = psa_mac_verify_setup(&operation,
|
||||
key_id,
|
||||
PSA_ALG_HMAC(PSA_ALG_SHA_256));
|
||||
}
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
status = psa_mac_update(&operation,
|
||||
indicator->hmac.idata,
|
||||
indicator->hmac.idata_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
status = psa_mac_verify_finish(&operation,
|
||||
indicator->hmac.mac,
|
||||
indicator->hmac.mac_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_HMAC;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_hmac(crypto_indicator_t *indicator)
|
||||
{
|
||||
if ((0 == indicator->hmac.key_id && NULL == indicator->hmac.key) ||
|
||||
NULL == indicator->hmac.idata || 0 == indicator->hmac.idata_len) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (PROP_HMAC_VERIFY == indicator->property && NULL == indicator->hmac.mac) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (NULL == indicator->hmac.mac && 0 == indicator->key_attr.import_req) {
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (ALG_HMAC != ALG_TYPE(indicator->algorithm)) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
switch (indicator->property) {
|
||||
case PROP_HMAC_COMPUTE:
|
||||
return crypto_wrapper_mac_compute(indicator->hmac.key_id, indicator);
|
||||
break;
|
||||
case PROP_HMAC_VERIFY:
|
||||
return crypto_wrapper_mac_verify(indicator->hmac.key_id, indicator);
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_INVALID_PARAM;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* \brief Generate random number.
|
||||
* \param[out] output Output buffer for generated random number
|
||||
* \param[in] output_size Number of bytes to generate and output
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_generate_random(uint8_t *output, uint32_t output_size)
|
||||
{
|
||||
psa_status_t status;
|
||||
|
||||
status = psa_generate_random(output, output_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return JEDEC_ERROR_GENERATE_RANDOM;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
const static crypto_func_t CRYPTO_FUNC[] = {
|
||||
0, //ALG_NONE 0
|
||||
crypto_wrapper_aes_ccm, //ALG_AES_CCM 1
|
||||
crypto_wrapper_aes_gcm, //ALG_AES_GCM 2
|
||||
crypto_wrapper_aes_ecb, //ALG_AES_ECB 3
|
||||
0, //ALG_AES_CBC 4
|
||||
0, //ALG_AES_OFB 5
|
||||
0, //ALG_AES_CTR 6
|
||||
0, //ALG_ECDSA 7
|
||||
0, //ALG_ECDH 8
|
||||
crypto_wrapper_hmac, //ALG_HMAC 9
|
||||
crypto_wrapper_mx78_kdf, //ALG_HKDF 10
|
||||
};
|
||||
|
||||
static int crypto_wrapper_algorithm_support(int alg, int index)
|
||||
{
|
||||
if (ALG_NONE == alg) {
|
||||
return JEDEC_ERROR_NOTHING;
|
||||
}
|
||||
if ((sizeof(CRYPTO_FUNC)/sizeof(crypto_func_t)) <= index || 0 == CRYPTO_FUNC[index]) {
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
static int crypto_wrapper_crypto_func(crypto_indicator_t *indicator)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE, index = ALG_TYPE(indicator->algorithm) >> 4;
|
||||
|
||||
status = crypto_wrapper_algorithm_support(indicator->algorithm, index);
|
||||
if (JEDEC_ERROR_NOTHING == status) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
return CRYPTO_FUNC[index](indicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate session key from root key.
|
||||
* \param[in] crypto_indicator KDF parameters
|
||||
* \param[out] session_key_id Returned session key id
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if success,
|
||||
* or JEDEC_ERROR_XX if fail
|
||||
*/
|
||||
static int crypto_wrapper_kdf(crypto_indicator_t *indicator,
|
||||
uint32_t *output_key_id)
|
||||
{
|
||||
int32_t status = JEDEC_ERROR_NONE, index = ALG_TYPE(indicator->algorithm) >> 4;
|
||||
|
||||
status = crypto_wrapper_algorithm_support(indicator->algorithm, index);
|
||||
if (JEDEC_ERROR_NOTHING == status) {
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return status;
|
||||
}
|
||||
status = CRYPTO_FUNC[index](indicator);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return JEDEC_ERROR_KDF;
|
||||
}
|
||||
switch (ALG_TYPE(indicator->algorithm)) {
|
||||
case ALG_HKDF:
|
||||
*output_key_id = indicator->hkdf.okm_id;
|
||||
break;
|
||||
case ALG_HMAC:
|
||||
*output_key_id = indicator->hmac.mac_id;
|
||||
break;
|
||||
default:
|
||||
return JEDEC_ERROR_NOT_SUPPORT;
|
||||
}
|
||||
return JEDEC_ERROR_NONE;
|
||||
}
|
||||
|
||||
crypto_wrapper_t mx78_armor_crypto_wrapper = {
|
||||
.init = crypto_wrapper_init,
|
||||
.deinit = crypto_wrapper_deinit,
|
||||
.algorithm_support = crypto_wrapper_algorithm_support,
|
||||
.crypto_func = crypto_wrapper_crypto_func,
|
||||
.key_derive = crypto_wrapper_kdf,
|
||||
.generate_random = crypto_wrapper_generate_random,
|
||||
.ecdh_gen_key_pair = crypto_wrapper_ecdh_gen_key_pair,
|
||||
.ecdh_gen_shared_secret = crypto_wrapper_ecdh_gen_shared_secret,
|
||||
.open_key = crypto_wrapper_open_key,
|
||||
.close_key = crypto_wrapper_close_key,
|
||||
.destroy_key = crypto_wrapper_destroy_key,
|
||||
.export_public_key = crypto_wrapper_export_public_key,
|
||||
.export_key = crypto_wrapper_export_key,
|
||||
.import_key = crypto_wrapper_import_key,
|
||||
|
||||
};
|
||||
#endif /* CRYPTO_PSA */
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _MX78_ARMOR_H_
|
||||
#define _MX78_ARMOR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../../../JEDEC_security_HAL/vendor_security_impl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SF_WARN_PR
|
||||
#define SF_DBG_PR
|
||||
#define SF_DBG0_PR
|
||||
#define SF_INFO_PR
|
||||
#define SF_ERR_PR
|
||||
#define SF_TMP_PR
|
||||
|
||||
#define SESSION_STATUS_EXHAUST 0x00
|
||||
#define SESSION_STATUS_ABUNDANT 0x01
|
||||
#define SESSION_STATUS_EMPTY 0x02
|
||||
#define MAX_NONCE_SIZE 0x10
|
||||
#define MAC_SIZE 0x20
|
||||
#define MAX_RESP_SIZE 0x150
|
||||
#define SCRATCHPAD_SIZE 0x150
|
||||
/* Extended configure registers number */
|
||||
#define EX_CR_NUM 0x06
|
||||
/* The max number of concurrent operations */
|
||||
#define CONC_OPER_NUM 0x04
|
||||
/* Data region configure size */
|
||||
#define CFG_SIZE_PER_REGION 0x04
|
||||
#define INVALID_SESSION_KEY_ID (0)
|
||||
/**
|
||||
* MX78 ArmorFlash supported security operations definition
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SECURITY_READ, /*!< Security read */
|
||||
SECURITY_WRITE, /*!< Security program */
|
||||
SECURITY_ERASE, /*!< Security erase */
|
||||
MC_INCREASEMENT, /*!< Increase Monotonic counter */
|
||||
MC_READ, /*!< Read Monotonic counter */
|
||||
GENERATE_NONCE, /*!< Generate nonce for cryptographic operations */
|
||||
READ_SESSION_STATUS, /*!< Read sessions status */
|
||||
CREATE_SESSION, /*!< Create new sessions */
|
||||
CONFIRM_SESSION, /*!< Session confirmation */
|
||||
TERMINATE_SESSION, /*!< Session termination */
|
||||
GEN_PRIV_KEY, /*!< Generate private key */
|
||||
GEN_PUB_KEY, /*!< Generate public key */
|
||||
EXPORT_PUB_KEY, /*!< Export public key */
|
||||
SYNC_HOST_PUB_KEY, /*!< Synchronize host public key */
|
||||
SYNC_SALT, /*!< Synchronize salt */
|
||||
GEN_ROOT_KEY, /*!< Generate root key */
|
||||
SECURITY_GET_REGION_CONFIG,
|
||||
GET_CFG, /*!< Read configuration information */
|
||||
SET_CFG,
|
||||
CFG_SECURITY_PROFILE,/*!< Configure security profile */
|
||||
SECURE_INIT,
|
||||
SECURE_UNINIT,
|
||||
HEALTH_TEST,
|
||||
LOCK_DOWN /*!< Lock down */
|
||||
} mx78_armor_operation_type_t;
|
||||
|
||||
enum {
|
||||
OPER_NOT_IN_USE = 0,
|
||||
OPER_IN_USE = 1,
|
||||
};
|
||||
|
||||
#define PACKET_OUT 0
|
||||
#define PACKET_IN 1
|
||||
|
||||
typedef enum {
|
||||
ITEM_DATA_CFG,
|
||||
ITEM_MC_CFG,
|
||||
ITEM_KEY_CFG,
|
||||
ITEM_LKD_CFG,
|
||||
ITEM_TOTAL_CFG,
|
||||
ITEM_MC,
|
||||
ITEM_KEY,
|
||||
ITEM_EXTRA,
|
||||
} mx78_armor_security_item_t;
|
||||
|
||||
/**
|
||||
* \struct mx78_armor_security_operation_t
|
||||
*
|
||||
* \brief The structure holding MX78 ArmorFlash security operations' context.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t in_use;
|
||||
mx78_armor_operation_type_t type; /*!< Security operation type */
|
||||
uint8_t *in_data; /*!< Pointer to current security operation input data */
|
||||
uint32_t in_size; /*!< Input data size in bytes */
|
||||
uint8_t *out_data; /*!< Pointer to current security operation output data */
|
||||
uint32_t out_size; /*!< Output data size in bytes */
|
||||
uint32_t addr; /*!< The access address of current security operation */
|
||||
union {
|
||||
uint8_t mc; /*!< Current security operation linked monotonic counter id */
|
||||
uint8_t profile; /*!< Current security operation linked security profile id */
|
||||
uint8_t region; /*!< Current security operation linked region id */
|
||||
uint32_t root_key; /*!< Current security operation linked root key id */
|
||||
} id;
|
||||
uint32_t crypto_key_id; /*!< Current security operation linked crypto service key id */
|
||||
} mx78_armor_security_operation_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t status_register;
|
||||
uint8_t configure_register;
|
||||
uint8_t configure_register_extend[EX_CR_NUM];//cr2
|
||||
uint8_t secure_register;
|
||||
} registers_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
registers_t regs;
|
||||
uint8_t scratchpad[SCRATCHPAD_SIZE];
|
||||
} mx78_armor_context;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MX78_ARMOR_H_ */
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _MX78_ARMOR_LIB_H_
|
||||
#define _MX78_ARMOR_LIB_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../../JEDEC_security_HAL/crypto_wrapper.h"
|
||||
#include "../../../JEDEC_security_HAL/include/jedec_defs.h"
|
||||
#include "mx78_armor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Check whether input session_key_id is valid.
|
||||
*
|
||||
* \param[in] session_key_id Input session_key_id
|
||||
* \param[out] session_key_valid_flag Session key validity flag
|
||||
* \return NULL
|
||||
*/
|
||||
void __mx78_armor_check_session_key_id_validity(uint32_t session_key_id,
|
||||
bool *session_key_valid_flag);
|
||||
/**
|
||||
* \brief Get security item's access address and size.
|
||||
*
|
||||
* \param[in] item Security item type
|
||||
* \param[out] addr Pointer to address
|
||||
* \param[out] size Pointer to size
|
||||
* \return JEDEC_ERROR_NONE on success, otherwise JEDEC_ERROR_XX
|
||||
*/
|
||||
int32_t __get_target_addr_and_size(mx78_armor_security_item_t item,
|
||||
uint32_t *addr, uint32_t *size);
|
||||
/**
|
||||
* \brief Get the minimum size of secure erase operation.
|
||||
*
|
||||
* \return The minimum size of secure erase operation.
|
||||
*/
|
||||
uint32_t __secure_erase_min_size(void);
|
||||
/**
|
||||
* \brief Get security operation's Nonce size.
|
||||
*
|
||||
* \param[in] params Security operation parameters
|
||||
*
|
||||
* \return Size of the nonce
|
||||
*/
|
||||
uint8_t __get_nonce_size(mx78_armor_security_operation_t *oper_ctx);
|
||||
/**
|
||||
* \brief Get security operation's linked monotonic counter id.
|
||||
*
|
||||
* \param[in] params Security operation parameters
|
||||
*
|
||||
* \return Monotonic counter id
|
||||
*/
|
||||
int32_t __get_linked_mc_id(mx78_armor_security_operation_t *oper_ctx);
|
||||
|
||||
/**
|
||||
* \brief Get security operation's to-be-received packet size.
|
||||
*
|
||||
* \param[in] params Security operation parameters
|
||||
* \param[out] rd_packet_len The size of to-be-received packet from secure Flash
|
||||
* \return NULL
|
||||
*/
|
||||
void __get_read_packet_size(mx78_armor_security_operation_t *oper_ctx,
|
||||
uint32_t *rd_packet_len);
|
||||
|
||||
/**
|
||||
* \brief Get the messages needed by AEAD cryptographic algorithm.
|
||||
*
|
||||
* \param[in] params Security operation parameters
|
||||
* \param[out] indicator The cryptographic indicator of AEAD cryptographic algorithm
|
||||
*
|
||||
* \return JEDEC_ERROR_XX
|
||||
*/
|
||||
int32_t __get_aead_msg(mx78_armor_security_operation_t *oper_ctx,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Get the messages needed by key derivation function.
|
||||
*
|
||||
* \param[in] root_key_id The id of kdf's input root key
|
||||
* \param[in] mc Pointer to the monotonic counter involved in key derivation
|
||||
* \param[in] mc_size The size of monotonic counter
|
||||
* \param[out] indicator The cryptographic indicator of key derivation operation
|
||||
* \return JEDEC_ERROR_XX
|
||||
*/
|
||||
int32_t __get_kdf_msg(uint32_t root_key_id,
|
||||
uint8_t *mc, uint32_t mc_size,
|
||||
crypto_indicator_t *indicator);
|
||||
/**
|
||||
* \brief Prepare write packet to be sent to secure Flash.
|
||||
*
|
||||
* \param[in] params Structure containing security operation's parameters
|
||||
* \param[in] buf Buffer containing ciphertext data
|
||||
* \param[in] buf_size The size of ciphertext data i bytes
|
||||
* \param[in] mac Buffer containing authentication code
|
||||
* \param[in] mac_size The size of authentication code
|
||||
* \param[out] wr_packet Pointer to write packet
|
||||
* \param[out] wr_packet_len The size of write packet in bytes
|
||||
* \param[out] rd_packet_len The size of read packet in bytes
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __prepare_write_packet(mx78_armor_security_operation_t *oper_ctx,
|
||||
uint8_t *buf, uint32_t buf_size,
|
||||
uint8_t *mac, uint8_t mac_size,
|
||||
uint8_t *wr_packet, uint32_t *wr_packet_len,
|
||||
uint32_t *rd_packet_len);
|
||||
|
||||
/**
|
||||
* \brief Pack the command packet to secure Flash.
|
||||
*
|
||||
* \param[in] ctx Secure flash context
|
||||
* \param[in] type Command packet type
|
||||
* \param[in] data Buffer holding command data
|
||||
* \param[in] data_size The buffer size
|
||||
* \param[out] tx_buffer Buffer to hold command packet
|
||||
* \param[out] tx_buffer_len The actual command packet size in byte
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
|
||||
int32_t __packet_assemble(mx78_armor_context *ctx, uint8_t type,
|
||||
uint8_t *data, uint32_t data_size,
|
||||
uint8_t *tx_buffer, uint32_t *tx_buffer_len);
|
||||
/**
|
||||
* \brief Pack the to-be-authenticated response from secure Flash.
|
||||
*
|
||||
* \param[in] params Security operation's parameters
|
||||
* \param[in] resp_buf Buffer to hold the response
|
||||
* \param[in] resp_buf_size The size of resp_buf
|
||||
* \param[out] actual_resp_len The actual packed response size in byte
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __pack_response(mx78_armor_security_operation_t *oper_ctx,
|
||||
uint8_t *resp_buf, uint32_t resp_buf_size,
|
||||
uint32_t *actual_resp_len);
|
||||
/**
|
||||
* \brief Parse secure Flash security configuration.
|
||||
*
|
||||
* \param[in] data_buf Buffer holding secure Flash security configuration
|
||||
* \param[in] data_size The size of secure Flash security configuration
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_security_configuration(uint8_t *data_buf, uint32_t data_size);
|
||||
/**
|
||||
* \brief Parse read packet received from secure Flash.
|
||||
*
|
||||
* \param[in] params Structure containing security operation's parameters
|
||||
* \param[out] buf Buffer to hold data parsed from read packet
|
||||
* \param[in] buf_size The size of data buf
|
||||
* \param[out] mac_buf Buffer to hold mac
|
||||
* \param[in] mac_size The size of mac
|
||||
* \param[in] rd_packet Pointer to read packet
|
||||
* \param[in] rd_packet_len The size of read packet in bytes
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_read_packet(mx78_armor_security_operation_t *oper_ctx,
|
||||
uint8_t *buf, uint32_t buf_size,
|
||||
uint8_t *mac_buf, uint8_t mac_size,
|
||||
uint8_t *rd_packet, uint32_t rd_packet_len);
|
||||
/**
|
||||
* \brief Parse region security description based on region configure.
|
||||
*
|
||||
* \param[in] oper_ctx Security operation's context
|
||||
* \param[out] region_descr_p Pointer to region description link list node
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_region_config(mx78_armor_security_operation_t *oper_ctx,
|
||||
region_ll_node_t *region_descr_p);
|
||||
/**
|
||||
* \brief Parse secure program response from secure Flash.
|
||||
*
|
||||
* \param[in] response_buffer Buffer containing response
|
||||
* \param[in] response_buffer_size The size of response buffer
|
||||
* \param[out] bytes_programmed The size of programmed data in byte
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_secure_program_response(uint8_t *response_buffer,
|
||||
uint16_t response_buffer_size,
|
||||
uint32_t *bytes_programmed);
|
||||
/**
|
||||
* \brief Parse secure erase response from secure Flash.
|
||||
*
|
||||
* \param[in] response_buffer Buffer containing response
|
||||
* \param[in] response_buffer_size The size of response buffer
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_secure_erase_response(uint8_t *response_buffer,
|
||||
uint32_t response_buffer_size);
|
||||
/**
|
||||
* \brief Parse secure read response from secure Flash.
|
||||
*
|
||||
* \param[in] response_buffer Buffer holding response
|
||||
* \param[in] response_buffer_size The size of response buffer
|
||||
* \param[out] data Buffer to hold data
|
||||
* \param[out] data_len Buffer length
|
||||
* \param[out] bytes_read The actual size of read data in byte
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_secure_read_response(uint8_t *response_buffer,
|
||||
uint16_t response_buffer_size,
|
||||
uint8_t *data, uint32_t data_len,
|
||||
uint32_t *bytes_read);
|
||||
/**
|
||||
* \brief Parse app info.
|
||||
*
|
||||
* \param[in] app_data Buffer holding app data
|
||||
* \param[in] info_size The size of app data
|
||||
* \param[in] app_data_num App data item number
|
||||
*
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t __parse_app_info(uint8_t *app_data, uint32_t info_size, uint8_t app_data_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MX78_ARMOR_LIB_H_ */
|
Binary file not shown.
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _MX78_ARMOR_PROVISION_H
|
||||
#define _MX78_ARMOR_PROVISION_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "../mx78_armor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file mx78_armor_provision.h
|
||||
*
|
||||
* \brief This file describes the structures of mx78 series secure Flash
|
||||
* provisioning data template
|
||||
*/
|
||||
|
||||
#define PROVISION_INFO_SIZE 0x80
|
||||
/**The template structure of provisioning data blob
|
||||
-----------------------------------------------------------
|
||||
| Magic |
|
||||
-----------------------------------------------------------
|
||||
|Sub header num |Sub header size | Version |
|
||||
-----------------------------------------------------------
|
||||
|Provision_disable | ID2 |ID1 |ID0 |
|
||||
| Reserved | Total size |
|
||||
-----------------------------------------------------------
|
||||
| Sub header 1:application info | /// app_info id; app_info num; each app_info size; app_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed application info | /// app_info id;
|
||||
| description | [app_id0, zone_id0, root_key_id0];[app_id1, zone_id1, root_key_id1]
|
||||
-----------------------------------------------------------
|
||||
| Sub header 2:key derivation info | /// key_info id; key_info num; each key_info size; key_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed key derivation info | /// key_info id; key exchange type: 00:send key directly to the other party
|
||||
| description | 01:DH
|
||||
-----------------------------------------------------------
|
||||
| Sub header 3:counter info |
|
||||
-----------------------------------------------------------
|
||||
| Detailed counter info | /// counter_info id;
|
||||
| description | [counter_id0, counter_init_value0];[counter_id1, counter_init_value1]
|
||||
-----------------------------------------------------------
|
||||
| Sub header 4:configure info | /// configure_info id; configure_info num; each configure_info size; configure_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed configure info | /// configure_info id;
|
||||
| description |
|
||||
-----------------------------------------------------------
|
||||
| Sub header 5:lock info | /// lock_info id; lock_info num; each lock_info size; lock_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed lock info | /// lock_info id;
|
||||
| description |
|
||||
-----------------------------------------------------------
|
||||
As it doesn't need to store the whole provisioning data, the size of
|
||||
provisioning data to be stored in memory is less than received provisioning data
|
||||
blob's size.
|
||||
The template structure of provisioning data in memory is similar to above
|
||||
provisioning data blob's structure.
|
||||
|
||||
The template structure of provisioning data stored in memory
|
||||
-----------------------------------------------------------
|
||||
| Magic |
|
||||
-----------------------------------------------------------
|
||||
|Sub header stored num |Sub header size | Version |
|
||||
-----------------------------------------------------------
|
||||
|Provision_disable | ID2 |ID1 |ID0 |
|
||||
| Reserved | Total stored size |
|
||||
-----------------------------------------------------------
|
||||
| Sub header 1:application info | /// app_info id; app_info num; each app_info size; app_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed application info | /// app_info id;
|
||||
| description | [app_id0, zone_id0, root_key_id0];[app_id1, zone_id1, root_key_id1]
|
||||
-----------------------------------------------------------
|
||||
| Sub header 2:key derivation info | /// key_info id; key_info num; each key_info size; key_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed key derivation info | /// key_info id; key exchange type: 00:send key directly to the other party
|
||||
| description | 01:DH
|
||||
-----------------------------------------------------------
|
||||
| Sub header 3:lock info | /// lock_info id; lock_info num; each lock_info size; lock_info storage flag
|
||||
-----------------------------------------------------------
|
||||
| Detailed lock info | /// lock_info id;
|
||||
| description | lock_type:counter/datazone/key/...
|
||||
-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define ARMOR_APP_INFO_MAX_NUM 16
|
||||
#define ARMOR_LKD_INFO_MAX_NUM 8
|
||||
#define KEY_INFO_MAX_NUM 16
|
||||
#define MC_INFO_MAX_NUM 16
|
||||
#define MC_MAX_SIZE 4
|
||||
#define CFG_INFO_MAX_NUM 0x60
|
||||
|
||||
/**
|
||||
* Sub items' header id of ArmorFlash provisioning information.
|
||||
*/
|
||||
typedef enum {
|
||||
SUB_ID_DATA_CONFIG_INFO = 0,
|
||||
SUB_ID_KEY_CONFIG_INFO = 1,
|
||||
SUB_ID_CNT_CONFIG_INFO = 2,
|
||||
SUB_ID_APP_INFO = 3,
|
||||
SUB_ID_KEY_INFO = 4,
|
||||
SUB_ID_MC_INFO = 5,
|
||||
SUB_ID_LOCK_INFO = 6,
|
||||
SUB_ID_MAX_NUMBER,
|
||||
} SubHeaderId;
|
||||
|
||||
|
||||
/**
|
||||
* \struct provision_sub_item_header_t
|
||||
*
|
||||
* \brief Structure holding each sub item's header of ArmorFlash provisioning
|
||||
* information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t id: 8, /*!< Sub item's header id */
|
||||
num: 8, /*!< Sub item's number */
|
||||
size: 15, /*!< Sub item's size */
|
||||
store: 1; /*!< Sub item's storage flag */
|
||||
} provision_sub_item_header_t;
|
||||
|
||||
|
||||
/**
|
||||
* \struct provision_major_header_t
|
||||
*
|
||||
* \brief Structure holding the major header of ArmorFlash provisioning
|
||||
* information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t magic[4]; /*!< The magic bytes of this
|
||||
provisioning information */
|
||||
uint32_t minor_version: 4, /*!< The version of this provisioning information */
|
||||
major_version: 4,
|
||||
sub_header_num: 8, /*!< The number of this provisioning
|
||||
information's sub headers */
|
||||
total_size: 16; /*!< The total size of this
|
||||
provisioning information */
|
||||
uint8_t id[4]; /*!< The secure Flash id */
|
||||
} provision_major_header_t;
|
||||
|
||||
#define SFPI_MAJOR_HEADER_SIZE (sizeof(provision_major_header_t))
|
||||
#define SFPI_SUB_HEADER_SIZE (sizeof(provision_sub_item_header_t))
|
||||
|
||||
/**
|
||||
* \struct mx_app_data_t
|
||||
*
|
||||
* \brief Structure to store a certain application item's
|
||||
* provisioning information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t app_id; /*!< Application id */
|
||||
uint32_t key_id; /*!< Application binded crypto key id */
|
||||
uint32_t zone_id:8, /*!< Application binded security zone id */
|
||||
mc_id:8, /*!< Application binded monotonic counter id */
|
||||
reserved:16;
|
||||
} mx_app_data_t;
|
||||
/**
|
||||
* \struct mx_app_info_t
|
||||
*
|
||||
* \brief Structure holding provisioning information for applications.
|
||||
*/
|
||||
typedef struct {
|
||||
provision_sub_item_header_t header;
|
||||
mx_app_data_t app_data[ARMOR_APP_INFO_MAX_NUM]; /*!< Buffer holding
|
||||
application items'
|
||||
provisioning
|
||||
information */
|
||||
} mx_app_info_t;
|
||||
|
||||
/** provision for lock_info
|
||||
*
|
||||
* DWORD 0: [07:00] ID, [31:08] reserved
|
||||
* DWORD 1: [07:00] config_regs, [15:08] ind_key_lock,
|
||||
* [23:16] ind_key_dis, [31:24] reserved
|
||||
* DWORD 2: [15:00] datazone lock(bitwise), [31:16] provision (bitwise)
|
||||
**/
|
||||
|
||||
/**
|
||||
* \struct lock_info_t
|
||||
*
|
||||
* \brief Structure holding provisioning information for
|
||||
* ArmorFlash's lock down configuration.
|
||||
*/
|
||||
typedef struct {
|
||||
provision_sub_item_header_t header;
|
||||
uint8_t lock_data[ARMOR_LKD_INFO_MAX_NUM]; /*!< Buffer holding lock
|
||||
down information */
|
||||
} lock_info_t;
|
||||
|
||||
/** provision for key_info
|
||||
*
|
||||
* DWORD 0: [07:00] ID, [15:08] key number, [31:16] Reserved
|
||||
* key 0
|
||||
* DWORD 1: [31:00] key id
|
||||
* DWORD 2: [31:00] key derive message
|
||||
* DWORD 3: [07:00] key derive params suite, [23:08] key length (in bytes),
|
||||
* [31:24] key inject type
|
||||
* key 1 ~ (key number -1)
|
||||
**/
|
||||
/**
|
||||
* \struct key_data_t
|
||||
*
|
||||
* \brief Structure holding provisioning information used to derive a
|
||||
* certain root key of ArmorFlash.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t key_id; /*!< Root key id */
|
||||
uint32_t derive_message; /*!< Specific information for root key
|
||||
derivation */
|
||||
uint32_t key_derive_suite: 8, /*!< Key derivation cipher algorithm */
|
||||
key_exchange_type: 4, /*!< Key exchange type: DH or directly share to the other party */
|
||||
key_len: 8, /*!< Derived root key length in bytes */
|
||||
zone_id: 8, /*!< Corresponding */
|
||||
inject_type: 4; /*!< The mode of synchronizing ArmorFlash's
|
||||
root key */
|
||||
} key_data_t;
|
||||
/**
|
||||
* \struct key_info_t
|
||||
*
|
||||
* \brief Structure holding provisioning information for ArmorFlash root keys
|
||||
* derivation.
|
||||
*/
|
||||
typedef struct {
|
||||
provision_sub_item_header_t header;
|
||||
key_data_t key_data[KEY_INFO_MAX_NUM]; /*!< Buffer holding root keys'
|
||||
provisioning information */
|
||||
} key_info_t;
|
||||
|
||||
/** provision for mc_info
|
||||
*
|
||||
* DWORD 0: [07:00] ID, [15:08] mc number, [31:16] reserved
|
||||
* mc 0
|
||||
* DWORD 1: [31:00] mc value
|
||||
* mc 1 ~ (mc number -1)
|
||||
**/
|
||||
typedef struct {
|
||||
uint8_t value[MC_MAX_SIZE]; // power of two, '0' is not supported
|
||||
} mc_data_t;
|
||||
/**
|
||||
* \struct mc_info_t
|
||||
*
|
||||
* \brief Structure holding ArmorFlash monotonic counters' provisioning
|
||||
* information.
|
||||
*/
|
||||
typedef struct {
|
||||
provision_sub_item_header_t header;
|
||||
mc_data_t mc_data[MC_INFO_MAX_NUM]; /*!< Buffer holding monotonic counters'
|
||||
provisioning information */
|
||||
} mc_info_t;
|
||||
|
||||
|
||||
/**
|
||||
* \struct config_info_t
|
||||
*
|
||||
* \brief Structure holding provisioning information used to configure ArmorFlash.
|
||||
*/
|
||||
typedef struct {
|
||||
provision_sub_item_header_t header;
|
||||
uint8_t config_data[CFG_INFO_MAX_NUM]; /*!< Buffer holding ArmorFlash
|
||||
configuration' provisioning
|
||||
information */
|
||||
} config_info_t;
|
||||
|
||||
int32_t mx78_armor_provision_perform(mx78_armor_context *mx78_armor_ctx,
|
||||
uint8_t *provision_data_blob,
|
||||
uint32_t data_size,
|
||||
uint8_t *provision_data_buf,
|
||||
uint32_t *data_store_size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _MX78_ARMOR_PROVISION_H */
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _SECUREFLASH_LAYOUT_H_
|
||||
#define _SECUREFLASH_LAYOUT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief Secure Flash name string. */
|
||||
#define SECURE_FLASH_NAME "mx78x64"
|
||||
#define SECURE_FLASH_SECURITY_STORAGE_CAP (1)
|
||||
#define SECURE_FLASH_SECTOR_SIZE (0x1000) /*!< The size of secure Flash's sector */
|
||||
#define SECURE_FLASH_ERASED_VALUE (0xFF) /*!< The erase value of secure Flash */
|
||||
#define SECURE_FLASH_PROGRAM_UNIT (0x01) /*!< The program unit of secure Flash */
|
||||
#define SECURE_FLASH_READ_UNIT (0x01) /*!< The read unit of secure Flash */
|
||||
#define SECURE_FLASH_PROGRAM_SIZE (0x100) /*!< The max data size of each secure program packet */
|
||||
#define SECURE_FLASH_READ_SIZE (0x100) /*!< The max data size of each secure read packet */
|
||||
#define SECURE_FLASH_SIZE (0x800000)
|
||||
#define SECURE_FLASH_ZONE_SIZE (0x80000)
|
||||
#define SECURE_FLASH_ZONE_NUM (SECURE_FLASH_SIZE / SECURE_FLASH_ZONE_SIZE)
|
||||
|
||||
#define SECURE_FLASH_MAX_PUF_SIZE (0x20)
|
||||
#define SECURE_FLASH_MAX_TRNG_SIZE (0x20)
|
||||
#define SECURE_FLASH_MAX_MC_SIZE (4)
|
||||
/** \brief If multi-client(or multi-application) isolation is defined,
|
||||
* the number of clients,
|
||||
* and the layout of secure Flash memory region should be defined.
|
||||
* Here takes four applications for example.
|
||||
*/
|
||||
#if defined(MULTI_CLIENT_ISOLATION) /*!< Enable multi-client isolation */
|
||||
/* multi-client secure flash layout*/
|
||||
/* Negative client id stands for clients from nspe;
|
||||
* Positive client id stands for clients from spe */
|
||||
#define SECURE_FLASH_CLIENT_NUM (3)
|
||||
#define SECURE_FLASH_CLIENT0_ID (-2) /*!< Client id 0:0xfffffffe */
|
||||
#define SECURE_FLASH_CLIENT0_AREA_START_ADDR (0) /*!< Start address of security memory region allocated for Client id 0 */
|
||||
#define SECURE_FLASH_CLIENT0_AREA_SIZE (SECURE_FLASH_ZONE_SIZE) /*!< The size of security memory region allocated for Client id 0 */
|
||||
#define SECURE_FLASH_CLIENT0_SECTORS_PER_BLOCK (4)
|
||||
#if (SECURE_FLASH_CLIENT_NUM > 1)
|
||||
#define SECURE_FLASH_CLIENT1_ID (-3) /*!< Client id 1:0xfffffffd */
|
||||
#define SECURE_FLASH_CLIENT1_AREA_START_ADDR (SECURE_FLASH_CLIENT0_AREA_START_ADDR + SECURE_FLASH_CLIENT0_AREA_SIZE) /*!< Start address of security memory region allocated for Client id 1 */
|
||||
#define SECURE_FLASH_CLIENT1_AREA_SIZE (SECURE_FLASH_ZONE_SIZE) /*!< The size of security memory region allocated for Client id 1 */
|
||||
#define SECURE_FLASH_CLIENT1_SECTORS_PER_BLOCK (4)
|
||||
#endif
|
||||
#if (SECURE_FLASH_CLIENT_NUM > 2)
|
||||
#define SECURE_FLASH_CLIENT2_ID (3002) /*!< Client id 2:0xbba */
|
||||
#define SECURE_FLASH_CLIENT2_AREA_START_ADDR (SECURE_FLASH_CLIENT1_AREA_START_ADDR + SECURE_FLASH_CLIENT1_AREA_SIZE) /*!< Start address of security memory region allocated for Client id 2 */
|
||||
#define SECURE_FLASH_CLIENT2_AREA_SIZE (SECURE_FLASH_ZONE_SIZE) /*!< The size of security memory region allocated for Client id 2 */
|
||||
#define SECURE_FLASH_CLIENT2_SECTORS_PER_BLOCK (4)
|
||||
#endif
|
||||
#if (SECURE_FLASH_CLIENT_NUM > 3)
|
||||
#define SECURE_FLASH_CLIENT3_ID (3006) /*!< Client id 3:0xbbe */
|
||||
#define SECURE_FLASH_CLIENT3_AREA_START_ADDR (SECURE_FLASH_CLIENT2_AREA_START_ADDR + SECURE_FLASH_CLIENT2_AREA_SIZE) /*!< Start address of security memory region allocated for Client id 3 */
|
||||
#define SECURE_FLASH_CLIENT3_AREA_SIZE (SECURE_FLASH_ZONE_SIZE) /*!< The size of security memory region allocated for Client id 3 */
|
||||
#define SECURE_FLASH_CLIENT3_SECTORS_PER_BLOCK (4)
|
||||
#endif
|
||||
#endif
|
||||
/* Multi client isolation disabled */
|
||||
#define SECURE_FLASH_START_ADDR (0) /*!< Start address of secure Flash's security memory region */
|
||||
#define SECURE_FLASH_DEFAULT_CLIENT_AREA_SIZE (SECURE_FLASH_ZONE_SIZE *2) /*!< Default client area size equals secure zone size */
|
||||
#define SECURE_FLASH_SECTORS_PER_BLOCK (4) /*!< The number of sectors of per secure Flash block */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SECUREFLASH_LAYOUT_H_ */
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
|
||||
#ifndef _VENDOR_PROVISIONING_IMPL_H_
|
||||
#define _VENDOR_PROVISIONING_IMPL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* secure Flash provisioning error definition */
|
||||
#define JEDEC_ERROR_PROVISION -0x2001
|
||||
#define JEDEC_ERROR_GET_PROVISION_INFO -0x2002
|
||||
#define JEDEC_ERROR_PROVISION_EXCHANGE_KEY -0x2003
|
||||
#define JEDEC_ERROR_PROVISION_SYNC_SALT -0x2004
|
||||
#define JEDEC_ERROR_PROVISION_GEN_ROOT_KEY -0x2005
|
||||
|
||||
typedef enum {
|
||||
ITEM_APP_INFO,
|
||||
ITEM_LKD_INFO,
|
||||
LAST_ITEM_TYPE
|
||||
}provision_item_type_e;
|
||||
|
||||
/**
|
||||
* \brief vendor specific provisioning operations
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* \brief Perform secure Flash provisioning and verify.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] provision_data Input provisioning data blob
|
||||
* \param[in] data_length The size of input provisioning data blob in bytes
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*perform_and_verify)(void *vendor_ctx,
|
||||
uint8_t *provision_data,
|
||||
uint32_t data_length);
|
||||
/**
|
||||
* \brief Get secure Flash provisioning item data.
|
||||
*
|
||||
* \param[in] vendor_ctx The vendor specific secure Flash context
|
||||
* \param[in] item_type Provisioning item type
|
||||
* \param[in] provision_data_buf Buffer to store provisioning item data
|
||||
* \param[in] provision_data_size Buffer size
|
||||
* \param[out] item_data_num The number of item entries
|
||||
* \param[out] provision_data_act_size Actual size of provisioning item data
|
||||
* \return JEDEC_ERROR_NONE if successful,
|
||||
* or a specific JEDEC_ERROR_XX error code
|
||||
*/
|
||||
int32_t (*provision_item_get_data)(void *vendor_ctx,
|
||||
provision_item_type_e item_type,
|
||||
uint8_t *provision_data_buf,
|
||||
uint32_t provision_data_size,
|
||||
uint8_t *item_data_num,
|
||||
uint32_t *provision_data_act_size);
|
||||
} vendor_provisioning_op_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VENDOR_PROVISIONING_IMPL_H_ */
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _VENDOR_SECUREFLASH_H_
|
||||
#define _VENDOR_SECUREFLASH_H_
|
||||
|
||||
#include "vendor_secureflash_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const secure_flash_info_t macronix_mx78_info;
|
||||
|
||||
const secure_flash_info_t *flash_info[] = {
|
||||
¯onix_mx78_info,
|
||||
/* Add secure flash info here */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VENDOR_SECUREFLASH_H_ */
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2020-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _VENDOR_SECUREFLASH_DEFS_H
|
||||
#define _VENDOR_SECUREFLASH_DEFS_H
|
||||
|
||||
#include "../JEDEC_security_HAL/jedec_security_hal.h"
|
||||
#include "vendor_provisioning_impl.h"
|
||||
#include "secureflash_layout.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SECURE_FLASH_MAX_ID_LEN 6
|
||||
|
||||
/*!
|
||||
* \struct security_feature_t
|
||||
*
|
||||
* \brief Structure to store the security features of secure Flash.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t security_storage: 1, /*!< Support security storage of data */
|
||||
rpmc: 1, /*!< Support replay protection monotonic counter */
|
||||
uid: 1, /*!< Support unique id */
|
||||
rng: 1, /*!< Support random number generator */
|
||||
puf: 1, /*!< Support physical unclonable function */
|
||||
reserved: 27; /*!< Reserved */
|
||||
} security_feature_t;
|
||||
|
||||
/*!
|
||||
* \struct cipher_suite_t
|
||||
*
|
||||
* \brief Structure to store the cipher suites of secure Flash.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t key_exchange_alg: 8, /*!< Key exchange algorithm */
|
||||
key_derive_alg: 8, /*!< Key derivation algorithm */
|
||||
encryption_alg: 8, /*!< Encryption algorithm */
|
||||
signature_alg:8; /*!< Signature algorithm */
|
||||
} cipher_suite_t;
|
||||
|
||||
/*!
|
||||
* \struct key_size_t
|
||||
*
|
||||
* \brief Structure to store secure Flash various keys' size.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t session_key_size: 16,
|
||||
private_key_size: 16;
|
||||
uint32_t public_key_size: 16,
|
||||
preshare_key_size: 16;
|
||||
uint32_t salt_key_size: 16,
|
||||
root_key_size: 16;
|
||||
uint32_t rpmc_root_key_size: 16,
|
||||
rpmc_hmac_key_size: 16;
|
||||
} key_size_t;
|
||||
|
||||
/*!
|
||||
* \struct architecture_t
|
||||
*
|
||||
* \brief Structure to store secure Flash architecture.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t erase_value;
|
||||
uint32_t secure_read_size; /*!< Security read size in bytes */
|
||||
uint32_t secure_program_size; /*!< Security program size in bytes */
|
||||
uint32_t secure_erase_size[4]; /*!< Security erase size in bytes */
|
||||
uint32_t regions_min_secure_erase_size; /*!< Minimum security erase size in bytes */
|
||||
uint32_t sector_size;
|
||||
uint32_t secure_zone_number; /*!< Secure data zone number */
|
||||
uint32_t secure_zone_size; /*!< Individual data zone size */
|
||||
uint32_t secure_zone_total_size; /*!< Whole data zones size */
|
||||
} architecture_t;
|
||||
|
||||
/*!
|
||||
* \struct flash_profile_t
|
||||
*
|
||||
* \brief Structure to store secure Flash profile.
|
||||
*/
|
||||
typedef struct {
|
||||
security_feature_t security_feature; /*!< Secure Flash security features */
|
||||
cipher_suite_t cipher_suite; /*!< Secure Flash cipher suites */
|
||||
key_size_t key_size; /*!< Secure Flash keys size */
|
||||
architecture_t architecture; /*!< Secure Flash architecture */
|
||||
} flash_profile_t;
|
||||
|
||||
|
||||
/*!
|
||||
* \struct secure_flash_info_t
|
||||
*
|
||||
* \brief Structure to store secure Flash specific information.
|
||||
*/
|
||||
typedef struct {
|
||||
char *name; /*! Secure Flash name */
|
||||
uint8_t id[SECURE_FLASH_MAX_ID_LEN]; /*! Secure Flash ID */
|
||||
uint8_t id_len; /*! Secure Flash ID length */
|
||||
flash_profile_t *flash_profile;
|
||||
vendor_security_op_t *vendor_security_op; /*! Vendor specific security operations */
|
||||
vendor_provisioning_op_t *vendor_provisioning_op; /*! Vendor specific secure Flash provisioning operations */
|
||||
crypto_wrapper_t *crypto_wrapper; /*! Vendor specific crypto wrapper functions */
|
||||
void *vendor_ctx; /*! Vendor specific context */
|
||||
} secure_flash_info_t;
|
||||
|
||||
extern const secure_flash_info_t macronix_mx78_info;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VENDOR_SECUREFLASH_DEFS_H */
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#include "vendor.h"
|
||||
#include "../../vendor_secureflash_defs.h"
|
||||
|
||||
extern crypto_wrapper_t vendor_crypto_wrapper;
|
||||
|
||||
static int32_t vendor_secureflash_pre_create_session(vendor_secureflash_context *secureflash_ctx,
|
||||
uint8_t *nonce_in, uint32_t nonce_in_len,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_create_session_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t root_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_create_session(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t root_key_id,
|
||||
uint32_t *session_key_id,
|
||||
uint8_t *nonce_in, uint32_t nonce_in_len,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SESSION_CONFIRMATION)
|
||||
static int32_t vendor_secureflash_pre_confirm_session()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
static int32_t vendor_secureflash_confirm_session_packet()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
static int32_t vendor_secureflash_post_confirm_session()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t vendor_secureflash_pre_terminate_session(vendor_secureflash_context *secureflash_ctx,
|
||||
uint8_t *nonce_in, uint32_t nonce_in_len,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_terminate_session_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *packet,uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_terminate_session(vendor_secureflash_context *secureflash_ctx,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_pre_secure_init(vendor_secureflash_context *secureflash_ctx,
|
||||
uint8_t *nonce_in, uint32_t nonce_in_len,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_init_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t root_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_secure_init(vendor_secureflash_context *secureflash_ctx,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_pre_secure_uninit(vendor_secureflash_context *secureflash_ctx,
|
||||
uint8_t *nonce_in, uint32_t nonce_in_len,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_uninit_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t root_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_secure_uninit(vendor_secureflash_context *secureflash_ctx,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_pre_secure_program(vendor_secureflash_context *secureflash_ctx, uint32_t addr,
|
||||
uint32_t session_key_id, jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_program_packet(vendor_secureflash_context *secureflash_ctx, uint32_t addr,
|
||||
const uint8_t *data, uint32_t len, uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_secure_program(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *resp_packet_buffer, uint32_t *resp_packet_buffer_size,
|
||||
crypto_indicator_t *indicator,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_parse_secure_program_response(vendor_secureflash_context *secureflash_ctx,
|
||||
crypto_indicator_t *indicator,
|
||||
uint32_t *bytes_programmed)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SECURE_READ)
|
||||
static int32_t vendor_secureflash_pre_secure_read(vendor_secureflash_context *secureflash_ctx, uint32_t addr,
|
||||
uint32_t session_key_id, jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_read_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t addr, uint32_t len, uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_secure_read(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *resp_packet_buffer,
|
||||
uint32_t *resp_packet_buffer_size,
|
||||
crypto_indicator_t *indicator,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_parse_secure_read_response(vendor_secureflash_context *secureflash_ctx,
|
||||
crypto_indicator_t *indicator,
|
||||
uint8_t *data, uint32_t data_len,
|
||||
uint32_t *bytes_read)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t vendor_secureflash_pre_secure_erase(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t addr, uint32_t len, uint32_t session_key_id,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_erase_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t addr, uint32_t len, uint32_t session_key_id,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_secure_erase(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t session_key_id,
|
||||
uint8_t *resp_packet_buffer,
|
||||
uint32_t *resp_packet_buffer_size,
|
||||
crypto_indicator_t *indicator,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_parse_secure_erase_response(vendor_secureflash_context *secureflash_ctx,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SECURE_COPY)
|
||||
static int32_t vendor_secureflash_pre_secure_copy()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_copy_packet()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
static int32_t vendor_secureflash_post_secure_copy()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t vendor_secureflash_pre_get_region_info(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t session_key_id, bool *session_key_valid_flag,
|
||||
jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_get_region_info_packet(vendor_secureflash_context *secureflash_ctx,
|
||||
uint32_t session_key_id, int8_t region_index,
|
||||
uint8_t *nonce_in, uint32_t nonce_in_len,
|
||||
uint8_t *packet, uint32_t *packet_len,
|
||||
crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_get_region_info(vendor_secureflash_context *secureflash_ctx,
|
||||
region_ll_node_t *region_descr_p, jqueue_t *resp_queue)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SECURE_REGION_MANAGE)
|
||||
static int32_t vendor_secureflash_pre_secure_manage_region()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_secure_manage_region_packet()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_post_secure_manage_region()
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t vendor_secureflash_packet_send(vendor_secureflash_context *secureflash_ctx,
|
||||
uint8_t *outdata, uint32_t outdata_len,
|
||||
uint8_t *cipher_text, uint32_t cipher_text_len,
|
||||
uint8_t *mac, uint32_t mac_len)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t vendor_secureflash_packet_receive(vendor_secureflash_context *secureflash_ctx,
|
||||
uint8_t *indata, uint32_t indata_len)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
vendor_security_op_t vendor_secureflash = {
|
||||
.vendor_id = VENOR_ID,
|
||||
.pre_create_session = vendor_secureflash_pre_create_session,
|
||||
.create_session_packet = vendor_secureflash_create_session_packet,
|
||||
.post_create_session = vendor_secureflash_post_create_session,
|
||||
#if defined(SESSION_CONFIRMATION)
|
||||
.pre_confirm_session = vendor_secureflash_pre_confirm_session,
|
||||
.confirm_session_packet = vendor_secureflash_confirm_session_packet,
|
||||
.post_confirm_session = vendor_secureflash_post_confirm_session,
|
||||
#endif
|
||||
.pre_terminate_session = vendor_secureflash_pre_terminate_session,
|
||||
.terminate_session_packet = vendor_secureflash_terminate_session_packet,
|
||||
.post_terminate_session = vendor_secureflash_post_terminate_session,
|
||||
.pre_secure_init = vendor_secureflash_pre_secure_init,
|
||||
.secure_init_packet = vendor_secureflash_secure_init_packet,
|
||||
.post_secure_init = vendor_secureflash_post_secure_init,
|
||||
.pre_secure_uninit = vendor_secureflash_pre_secure_uninit,
|
||||
.secure_uninit_packet = vendor_secureflash_secure_uninit_packet,
|
||||
.post_secure_uninit = vendor_secureflash_post_secure_uninit,
|
||||
|
||||
.pre_secure_program = vendor_secureflash_pre_secure_program,
|
||||
.secure_program_packet = vendor_secureflash_secure_program_packet,
|
||||
.post_secure_program = vendor_secureflash_post_secure_program,
|
||||
.parse_secure_program_response = vendor_secureflash_parse_secure_program_response,
|
||||
|
||||
.pre_secure_erase = vendor_secureflash_pre_secure_erase,
|
||||
.secure_erase_packet = vendor_secureflash_secure_erase_packet,
|
||||
.post_secure_erase = vendor_secureflash_post_secure_erase,
|
||||
.parse_secure_erase_response = vendor_secureflash_parse_secure_erase_response,
|
||||
#if defined(SECURE_COPY)
|
||||
.pre_secure_copy = vendor_secureflash_pre_secure_copy,
|
||||
.secure_copy_packet = vendor_secureflash_secure_copy_packet,
|
||||
.post_secure_copy = vendor_secureflash_post_secure_copy,
|
||||
#endif
|
||||
#if defined(SECURE_READ)
|
||||
.pre_secure_read = vendor_secureflash_pre_secure_read,
|
||||
.secure_read_packet = vendor_secureflash_secure_read_packet,
|
||||
.post_secure_read = vendor_secureflash_post_secure_read,
|
||||
.parse_secure_read_response = vendor_secureflash_parse_secure_read_response,
|
||||
#endif
|
||||
.pre_secure_get_regions_info = vendor_secureflash_pre_get_region_info,
|
||||
.secure_get_regions_info_packet = vendor_secureflash_get_region_info_packet,
|
||||
.post_secure_get_regions_info = vendor_secureflash_post_get_region_info,
|
||||
#if defined(SECURE_REGION_MANAGE)
|
||||
.pre_secure_manage_region = vendor_secureflash_pre_secure_manage_region,
|
||||
.secure_manage_region_packet = vendor_secureflash_secure_manage_region_packet,
|
||||
.post_secure_manage_region = vendor_secureflash_post_secure_manage_region,
|
||||
#endif
|
||||
.packet_send = vendor_secureflash_packet_send,
|
||||
.packet_receive = vendor_secureflash_packet_receive,
|
||||
};
|
||||
|
||||
const secure_flash_info_t vendor_secure_flash_info = {
|
||||
.id = {0xff, 0xff, 0xff},
|
||||
.id_len = 3,
|
||||
.vendor_security_op = &vendor_secureflash,
|
||||
.crypto_wrapper = &vendor_crypto_wrapper,
|
||||
};
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _VENDOR_H_
|
||||
#define _VENDOR_H_
|
||||
|
||||
#include "../../../JEDEC_security_HAL/vendor_security_impl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define your macros here
|
||||
*
|
||||
*/
|
||||
#define VENOR_ID 0xFF
|
||||
|
||||
/**
|
||||
* Secure Flash supported security operations definition
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
SECURITY_READ, /*!< Security read */
|
||||
SECURITY_WRITE, /*!< Security program */
|
||||
SECURITY_ERASE, /*!< Security erase */
|
||||
MC_INCREASEMENT, /*!< Increase monotonic counter */
|
||||
MC_READ, /*!< Read monotonic counter */
|
||||
GENERATE_NONCE, /*!< Generate random number */
|
||||
CREATE_SESSION, /*!< Session creation */
|
||||
CONFIRM_SESSION, /*!< Session confirmation */
|
||||
TERMINATE_SESSION, /*!< Session termination */
|
||||
GEN_ROOT_KEY, /*!< Generate root key */
|
||||
SECURITY_GET_REGION_CONFIG, /*!< Get region configure in security */
|
||||
CFG_SECURITY_PROFILE, /*!< Set secure Flash security profile */
|
||||
SECURE_INIT, /*!< Initialize in security */
|
||||
SECURE_UNINIT, /*!< Unitialize in security */
|
||||
LOCK_DOWN /*!< Lock down */
|
||||
/* Add secure Flash operations here */
|
||||
//TODO
|
||||
} vendor_secureflash_operation_type_t;
|
||||
|
||||
/**
|
||||
* \struct vendor_secureflash_security_operation_t
|
||||
*
|
||||
* \brief The structure holding secure Flash security operations' context.
|
||||
*/
|
||||
typedef struct {
|
||||
//TODO
|
||||
} vendor_secureflash_security_operation_t;
|
||||
|
||||
|
||||
/**
|
||||
* \struct secureflash_registers_t
|
||||
*
|
||||
* \brief The structure holding secure Flash registers' value.
|
||||
*/
|
||||
typedef struct {
|
||||
//TODO
|
||||
} secureflash_registers_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
//TODO
|
||||
/* Add vendor context members here */
|
||||
} vendor_secureflash_context;
|
||||
|
||||
extern vendor_security_op_t vendor_secureflash;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _VENDOR_H_ */
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "../../../JEDEC_security_HAL/crypto_wrapper.h"
|
||||
|
||||
#define KEY_HANDLE_NOT_LOADED (0)
|
||||
#define MAC_SIZE
|
||||
#define TAG_LENGTH
|
||||
#define MAX_ROOT_KEY_NUM
|
||||
#define MAX_SESSION_KEY_NUM
|
||||
#define MAC_KEY_SIZE
|
||||
#define ENC_KEY_SIZE
|
||||
|
||||
|
||||
typedef struct {
|
||||
//TODO
|
||||
}session_key_id_t;
|
||||
|
||||
|
||||
static int crypto_wrapper_init(void)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_deinit(void)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_algorithm_support(int alg, int index)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_crypto_func(crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
static int crypto_wrapper_kdf(crypto_indicator_t *indicator,
|
||||
uint32_t *output_key_id)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_generate_random(uint8_t *output, uint32_t output_size)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_ecdh_gen_key_pair(crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_ecdh_gen_shared_secret(crypto_indicator_t *indicator)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_open_key(uint32_t root_key_id)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_close_key(uint32_t root_key_id)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
static int crypto_wrapper_destroy_key(uint32_t key_id)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_export_public_key(uint32_t key_id, uint8_t *key_buf,
|
||||
uint32_t buf_size, uint32_t *actual_size)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_export_key(uint32_t key_id, uint8_t *key_buf,
|
||||
uint32_t buf_size, uint32_t *actual_size)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static int crypto_wrapper_import_key(uint32_t *key_id, uint8_t *key_buf,
|
||||
uint32_t key_size, KeyLifeTime lifetime)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
crypto_wrapper_t vendor_crypto_wrapper = {
|
||||
.init = crypto_wrapper_init,
|
||||
.deinit = crypto_wrapper_deinit,
|
||||
.algorithm_support = crypto_wrapper_algorithm_support,
|
||||
.crypto_func = crypto_wrapper_crypto_func,
|
||||
.key_derive = crypto_wrapper_kdf,
|
||||
.generate_random = crypto_wrapper_generate_random,
|
||||
.ecdh_gen_key_pair = crypto_wrapper_ecdh_gen_key_pair,
|
||||
.ecdh_gen_shared_secret = crypto_wrapper_ecdh_gen_shared_secret,
|
||||
.open_key = crypto_wrapper_open_key,
|
||||
.close_key = crypto_wrapper_close_key,
|
||||
.destroy_key = crypto_wrapper_destroy_key,
|
||||
.export_public_key = crypto_wrapper_export_public_key,
|
||||
.export_key = crypto_wrapper_export_key,
|
||||
.import_key = crypto_wrapper_import_key,
|
||||
};
|
|
@ -0,0 +1,312 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBED_SECUREFLASH_BLOCK_DEVICE_H
|
||||
#define MBED_SECUREFLASH_BLOCK_DEVICE_H
|
||||
|
||||
#include "platform/SingletonPtr.h"
|
||||
#include "drivers/SPI.h"
|
||||
#include "drivers/DigitalOut.h"
|
||||
#include "blockdevice/internal/SFDP.h"
|
||||
#include "blockdevice/BlockDevice.h"
|
||||
|
||||
#include "../../TG424_3/vendor_impl/vendor_secureflash_defs.h"
|
||||
|
||||
#ifndef MBED_CONF_SECUREF_DRIVER_SPI_MOSI
|
||||
#define MBED_CONF_SECUREF_DRIVER_SPI_MOSI NC
|
||||
#endif
|
||||
#ifndef MBED_CONF_SECUREF_DRIVER_SPI_MISO
|
||||
#define MBED_CONF_SECUREF_DRIVER_SPI_MISO NC
|
||||
#endif
|
||||
#ifndef MBED_CONF_SECUREF_DRIVER_SPI_CLK
|
||||
#define MBED_CONF_SECUREF_DRIVER_SPI_CLK NC
|
||||
#endif
|
||||
#ifndef MBED_CONF_SECUREF_DRIVER_SPI_CS
|
||||
#define MBED_CONF_SECUREF_DRIVER_SPI_CS NC
|
||||
#endif
|
||||
#ifndef MBED_CONF_SECUREF_DRIVER_SPI_FREQ
|
||||
#define MBED_CONF_SECUREF_DRIVER_SPI_FREQ 40000000
|
||||
#endif
|
||||
|
||||
#define APP_INFO_MAX_NUM (0x10)
|
||||
|
||||
/** Enum spif standard error codes
|
||||
*
|
||||
* @enum spif_bd_error
|
||||
*/
|
||||
enum securef_bd_error {
|
||||
SECUREF_BD_ERROR_OK = 0, /*!< no error */
|
||||
SECUREF_BD_ERROR_DEVICE_ERROR = mbed::BD_ERROR_DEVICE_ERROR, /*!< device specific error -4001 */
|
||||
SECUREF_BD_ERROR_PARSING_FAILED = -4002, /* SFDP Parsing failed */
|
||||
SECUREF_BD_ERROR_READY_FAILED = -4003, /* Wait for Memory Ready failed */
|
||||
SECUREF_BD_ERROR_WREN_FAILED = -4004, /* Write Enable Failed */
|
||||
SECUREF_BD_ERROR_INVALID_ERASE_PARAMS = -4005, /* Erase command not on sector aligned addresses or exceeds device size */
|
||||
SECUREF_BD_ERROR_DEVICE_UNSUPPORT = -4006, /* Device id match failed */
|
||||
SECUREF_BD_ERROR_PROVISION_FLASH = -4007, /* Provision secure flash failed */
|
||||
SECUREF_BD_ERROR_GET_PROVISION = -4007, /* Get the information of provision failed */
|
||||
SECUREF_BD_ERROR_ILLEGAL_ACCESS = -4008, /* Operation illegal */
|
||||
SECUREF_BD_ERROR_CREATE_SESSION = -4009, /* Create sessopm failed */
|
||||
SECUREF_BD_ERROR_TERMINATE_SESSION = -4010, /* Terminate sessopm failed */
|
||||
SECUREF_BD_ERROR_SECURE_READ = -4011, /* Secure read failed */
|
||||
SECUREF_BD_ERROR_SECURE_PROGRAM = -4012, /* Secure program failed */
|
||||
SECUREF_BD_ERROR_SECURE_ERASE = -4013, /* Secure erase failed */
|
||||
SECUREF_BD_ERROR_INVALID_PGM_PARAMS = -4014, /* Program command invalid arguments */
|
||||
SECUREF_BD_ERROR_INVALID_READ_PARAMS = -4015, /* Read command invalid arguments */
|
||||
};
|
||||
|
||||
/**
|
||||
* app_data_t
|
||||
*
|
||||
* Structure to store the pre-provisioned application & secure zone binding information.
|
||||
*/
|
||||
typedef struct {
|
||||
int32_t app_id; /*!< The id of applications */
|
||||
uint32_t key_id; /*!< The id of crypto root keys */
|
||||
uint32_t zone_id:8, /*!< The id of security zone id */
|
||||
mc_id:8, /*!< The id of monotonic counter */
|
||||
reserved:16;
|
||||
} app_data_t;
|
||||
|
||||
/**
|
||||
* app_info_t
|
||||
*
|
||||
* Structure to store the pre-provisioned application information.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t id; /*!< The id of app info */
|
||||
uint8_t num; /*!< The number of app_data items */
|
||||
app_data_t app_data[APP_INFO_MAX_NUM]; /*!< The detailed app_data */
|
||||
} app_info_t;
|
||||
|
||||
/**
|
||||
* session_info_t
|
||||
*
|
||||
* Structure to store secure Flash session information.
|
||||
*/
|
||||
typedef struct{
|
||||
uint32_t key_id; /*!< Root key id */
|
||||
uint32_t session_key_id; /*!< Session key id */
|
||||
uint32_t session_id; /*!< Session id */
|
||||
} session_info_t;
|
||||
|
||||
/**
|
||||
* secureflash_t
|
||||
*
|
||||
* Structure indicating secure Flash API layer informations
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t _init_ref_count; /*!< The initialization count of secure Flash */
|
||||
bool _is_initialized; /*!< Secure Flash initialization status */
|
||||
app_info_t app_info; /*!< The pre-provisioned application information of secure Flash */
|
||||
secure_flash_info_t flash_info; /*!< The specific secure Flash information */
|
||||
} secureflash_t;
|
||||
|
||||
class SecureFBlockDevice : public mbed::BlockDevice {
|
||||
public:
|
||||
/** Creates a SecureFBlockDevice on a SPI bus specified by pins
|
||||
*
|
||||
* @param mosi SPI master out, slave in pin
|
||||
* @param miso SPI master in, slave out pin
|
||||
* @param sclk SPI clock pin
|
||||
* @param csel SPI chip select pin
|
||||
* @param freq Clock speed of the SPI bus (defaults to 40MHz)
|
||||
*
|
||||
*
|
||||
*/
|
||||
SecureFBlockDevice(PinName mosi = MBED_CONF_SECUREF_DRIVER_SPI_MOSI,
|
||||
PinName miso = MBED_CONF_SECUREF_DRIVER_SPI_MISO,
|
||||
PinName sclk = MBED_CONF_SECUREF_DRIVER_SPI_CLK,
|
||||
PinName csel = MBED_CONF_SECUREF_DRIVER_SPI_CS,
|
||||
int freq = MBED_CONF_SECUREF_DRIVER_SPI_FREQ);
|
||||
|
||||
/** Initialize a block device
|
||||
*
|
||||
* @return SPIF_BD_ERROR_OK(0) - success
|
||||
* SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
|
||||
* SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
|
||||
* SPIF_BD_ERROR_PARSING_FAILED - unexpected format or values in one of the SFDP tables
|
||||
*/
|
||||
virtual int init();
|
||||
|
||||
/** Deinitialize a block device
|
||||
*
|
||||
* @return SPIF_BD_ERROR_OK(0) - success
|
||||
*/
|
||||
virtual int deinit();
|
||||
|
||||
/** Desctruct SPIFBlockDevice
|
||||
*/
|
||||
~SecureFBlockDevice()
|
||||
{
|
||||
deinit();
|
||||
}
|
||||
|
||||
/** Read blocks from a block device
|
||||
*
|
||||
* @param buffer Buffer to write blocks to
|
||||
* @param addr Address of block to begin reading from
|
||||
* @param size Size to read in bytes, must be a multiple of read block size
|
||||
* @return SPIF_BD_ERROR_OK(0) - success
|
||||
* SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
|
||||
*/
|
||||
virtual int read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
|
||||
|
||||
/** Program blocks to a block device
|
||||
*
|
||||
* @note The blocks must have been erased prior to being programmed
|
||||
*
|
||||
* @param buffer Buffer of data to write to blocks
|
||||
* @param addr Address of block to begin writing to
|
||||
* @param size Size to write in bytes, must be a multiple of program block size
|
||||
* @return SPIF_BD_ERROR_OK(0) - success
|
||||
* SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
|
||||
* SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
|
||||
* SPIF_BD_ERROR_WREN_FAILED - Write Enable failed
|
||||
*/
|
||||
virtual int program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size);
|
||||
|
||||
/** Erase blocks on a block device
|
||||
*
|
||||
* @note The state of an erased block is undefined until it has been programmed
|
||||
*
|
||||
* @param addr Address of block to begin erasing
|
||||
* @param size Size to erase in bytes, must be a multiple of erase block size
|
||||
* @return SPIF_BD_ERROR_OK(0) - success
|
||||
* SPIF_BD_ERROR_DEVICE_ERROR - device driver transaction failed
|
||||
* SPIF_BD_ERROR_READY_FAILED - Waiting for Memory ready failed or timed out
|
||||
* SPIF_BD_ERROR_INVALID_ERASE_PARAMS - Trying to erase unaligned address or size
|
||||
*/
|
||||
virtual int erase(mbed::bd_addr_t addr, mbed::bd_size_t size);
|
||||
|
||||
/** Get the size of a readable block
|
||||
*
|
||||
* @return Size of a readable block in bytes
|
||||
*/
|
||||
|
||||
virtual int secure_read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id);
|
||||
virtual int secure_program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id);
|
||||
virtual int secure_erase(mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id);
|
||||
virtual bd_size_t secure_zone_number() const;
|
||||
virtual bd_size_t secure_zone_size() const;
|
||||
|
||||
virtual mbed::bd_size_t get_read_size() const;
|
||||
|
||||
/** Get the size of a programable block
|
||||
*
|
||||
* @return Size of a programable block in bytes
|
||||
* @note Must be a multiple of the read size
|
||||
*/
|
||||
virtual mbed::bd_size_t get_program_size() const;
|
||||
|
||||
/** Get the size of an erasable block
|
||||
*
|
||||
* @return Size of an erasable block in bytes
|
||||
* @note Must be a multiple of the program size
|
||||
*/
|
||||
virtual mbed::bd_size_t get_erase_size() const;
|
||||
|
||||
/** Get the size of minimal erasable sector size of given address
|
||||
*
|
||||
* @param addr Any address within block queried for erase sector size (can be any address within flash size offset)
|
||||
* @return Size of minimal erase sector size, in given address region, in bytes
|
||||
* @note Must be a multiple of the program size
|
||||
*/
|
||||
virtual mbed::bd_size_t get_erase_size(mbed::bd_addr_t addr) const;
|
||||
|
||||
/** Get the value of storage byte after it was erased
|
||||
*
|
||||
* If get_erase_value returns a non-negative byte value, the underlying
|
||||
* storage is set to that value when erased, and storage containing
|
||||
* that value can be programmed without another erase.
|
||||
*
|
||||
* @return The value of storage when erased, or -1 if you can't
|
||||
* rely on the value of erased storage
|
||||
*/
|
||||
virtual int get_erase_value() const;
|
||||
|
||||
/** Get the total size of the underlying device
|
||||
*
|
||||
* @return Size of the underlying device in bytes
|
||||
*/
|
||||
virtual mbed::bd_size_t size() const;
|
||||
|
||||
/** Get the BlockDevice class type.
|
||||
*
|
||||
* @return A string representation of the BlockDevice class type.
|
||||
*/
|
||||
virtual const char *get_type() const;
|
||||
|
||||
private:
|
||||
/********************************/
|
||||
/* Calls to SPI Driver APIs */
|
||||
/********************************/
|
||||
|
||||
// Send set_frequency command to Driver
|
||||
securef_bd_error _spi_set_frequency(int freq);
|
||||
/********************************/
|
||||
|
||||
// Soft Reset Flash Memory
|
||||
int _reset_flash_mem();
|
||||
|
||||
// Configure Write Enable in Status Register
|
||||
int _set_write_enable();
|
||||
|
||||
// Wait on status register until write not-in-progress
|
||||
bool _is_mem_ready();
|
||||
|
||||
// Query vendor ID and handle special behavior that isn't covered by SFDP data
|
||||
int _handle_vendor_quirks();
|
||||
|
||||
// Probe secure flash
|
||||
int _probe();
|
||||
|
||||
// Find the flash_info
|
||||
int _find_flash_info(uint8_t *id);
|
||||
|
||||
// Get the information of provision
|
||||
int _secureflash_get_app_info();
|
||||
|
||||
// SPI protocol read
|
||||
static int _spi_read(uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len);
|
||||
|
||||
// SPI protocol program
|
||||
static int _spi_write(uint8_t *tx_buf, uint32_t tx_len);
|
||||
|
||||
app_data_t *_query_app_info(mbed::bd_addr_t addr, int app_id);
|
||||
|
||||
private:
|
||||
// Master side hardware
|
||||
static mbed::SPI *_spi;
|
||||
|
||||
PinName _mosi;
|
||||
PinName _miso;
|
||||
PinName _sclk;
|
||||
PinName _csel;
|
||||
int _freq;
|
||||
|
||||
// Mutex is used to protect Flash device for some SPI Driver commands that must be done sequentially with no other commands in between
|
||||
// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
|
||||
static SingletonPtr<PlatformMutex> _mutex;
|
||||
|
||||
// Bus configuration
|
||||
uint32_t _init_ref_count;
|
||||
bool _is_initialized;
|
||||
|
||||
// Struct for secure flash information
|
||||
secureflash_t _secureflash;
|
||||
};
|
||||
|
||||
#endif /* MBED_SECUREFLASH_BLOCK_DEVICE_H */
|
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
"name": "securef-driver",
|
||||
"config": {
|
||||
"param1": {
|
||||
"help": "Enable mbedtls based crypto wrapper",
|
||||
"macro_name": "CRYPTO_MBEDTLS",
|
||||
"value": 1
|
||||
},
|
||||
"param2": {
|
||||
"help": "Enable provisioning flow",
|
||||
"macro_name": "SECUREFLASH_PROVISION",
|
||||
"value": 1
|
||||
},
|
||||
"param3": {
|
||||
"help": "Enable test mode",
|
||||
"macro_name": "MX78_ARMOR_TEST_MODE",
|
||||
"value": 1
|
||||
},
|
||||
"SPI_MOSI": "SPI_MOSI",
|
||||
"SPI_MISO": "SPI_MISO",
|
||||
"SPI_CLK": "SPI_SCK",
|
||||
"SPI_CS": "SPI_CS",
|
||||
"SPI_FREQ": "40000000",
|
||||
"debug": {
|
||||
"help": "Enable debug logs. [0/1]",
|
||||
"options" : [0, 1],
|
||||
"value": 1
|
||||
}
|
||||
},
|
||||
"target_overrides": {
|
||||
"HANI_IOT": {
|
||||
"SPI_MOSI": "P0_26",
|
||||
"SPI_MISO": "P1_3",
|
||||
"SPI_CLK": "P1_2",
|
||||
"SPI_CS": "P0_20"
|
||||
},
|
||||
"LPC54114": {
|
||||
"SPI_MOSI": "P0_20",
|
||||
"SPI_MISO": "P0_18",
|
||||
"SPI_CLK": "P0_19",
|
||||
"SPI_CS": "P1_2"
|
||||
},
|
||||
"NRF52840_DK": {
|
||||
"SPI_MOSI": "p20",
|
||||
"SPI_MISO": "p21",
|
||||
"SPI_CLK": "p19",
|
||||
"SPI_CS": "p17"
|
||||
},
|
||||
"HEXIWEAR": {
|
||||
"SPI_MOSI": "PTD6",
|
||||
"SPI_MISO": "PTD7",
|
||||
"SPI_CLK": "PTD5",
|
||||
"SPI_CS": "PTD4"
|
||||
},
|
||||
"WIO_EMW3166": {
|
||||
"SPI_MOSI": "PB_15",
|
||||
"SPI_MISO": "PB_14",
|
||||
"SPI_CLK": "PB_13",
|
||||
"SPI_CS": "PA_10"
|
||||
},
|
||||
"ADV_WISE_1570": {
|
||||
"SPI_MOSI": "PA_7",
|
||||
"SPI_MISO": "PA_6",
|
||||
"SPI_CLK": "PA_5",
|
||||
"SPI_CS": "PB_12",
|
||||
"SPI_FREQ": "20000000"
|
||||
},
|
||||
"UHURU_RAVEN": {
|
||||
"SPI_MOSI": "PE_14",
|
||||
"SPI_MISO": "PE_13",
|
||||
"SPI_CLK": "PE_12",
|
||||
"SPI_CS": "PE_11"
|
||||
},
|
||||
"MTS_DRAGONFLY_F411RE": {
|
||||
"SPI_MOSI": "SPI3_MOSI",
|
||||
"SPI_MISO": "SPI3_MISO",
|
||||
"SPI_CLK": "SPI3_SCK",
|
||||
"SPI_CS": "SPI_CS1"
|
||||
},
|
||||
"MTS_DRAGONFLY_F413RH": {
|
||||
"SPI_MOSI": "SPI3_MOSI",
|
||||
"SPI_MISO": "SPI3_MISO",
|
||||
"SPI_CLK": "SPI3_SCK",
|
||||
"SPI_CS": "SPI_CS1"
|
||||
},
|
||||
"NUCLEO_L4R5ZI_P": {
|
||||
"SPI_MOSI": "PA_7",
|
||||
"SPI_MISO": "PA_6",
|
||||
"SPI_CLK": "PA_1",
|
||||
"SPI_CS": "PA_5"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _PLATFORM_IMPL_H_
|
||||
#define _PLATFORM_IMPL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t plat_store_secure_flash_provision_info(uint8_t *buffer, int size);
|
||||
int32_t plat_get_secure_flash_provision_info(uint8_t *buffer, uint32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _PLATFORM_IMPL_H_ */
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "../include/plat_secure_flash.h"
|
||||
#include "FlashIAPBlockDevice.h"
|
||||
|
||||
#define PROVISION_INFO_SIZE 0x1000
|
||||
|
||||
static inline uint32_t align_up(uint32_t val, uint32_t size)
|
||||
{
|
||||
return (((val - 1) / size) + 1) * size;
|
||||
}
|
||||
|
||||
int32_t plat_store_secure_flash_provision_info(uint8_t *buffer, int size)
|
||||
{
|
||||
#if COMPONENT_FLASHIAP
|
||||
#if (MBED_CONF_FLASHIAP_BLOCK_DEVICE_SIZE == 0) && (MBED_CONF_FLASHIAP_BLOCK_DEVICE_BASE_ADDRESS == 0xFFFFFFFF)
|
||||
int status;
|
||||
uint32_t actual_size = 0;
|
||||
uint32_t bottom_addr, provision_start_addr, last_addr, erase_addr, program_addr;
|
||||
|
||||
mbed::FlashIAP flash;
|
||||
status = flash.init();
|
||||
if (0 != status) {
|
||||
return -1;
|
||||
}
|
||||
//Find the start of first sector after text area
|
||||
bottom_addr = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR));
|
||||
last_addr = flash.get_flash_start() + flash.get_flash_size();
|
||||
status = flash.deinit();
|
||||
if (0 != status) {
|
||||
return -1;
|
||||
}
|
||||
FlashIAPBlockDevice iap_bd(bottom_addr, last_addr - bottom_addr);
|
||||
#else
|
||||
FlashIAPBlockDevice iap_bd;
|
||||
#endif
|
||||
provision_start_addr = last_addr - 1;
|
||||
while (actual_size < PROVISION_INFO_SIZE) {
|
||||
provision_start_addr -= flash.get_sector_size(provision_start_addr);
|
||||
actual_size += flash.get_sector_size(provision_start_addr);
|
||||
}
|
||||
if ((provision_start_addr + 1) < bottom_addr) {
|
||||
return -1;
|
||||
}
|
||||
provision_start_addr = provision_start_addr - bottom_addr + 1;
|
||||
|
||||
status = iap_bd.init();
|
||||
if (0 != status) {
|
||||
printf("Error : iap init failed.\r\n");
|
||||
return -1;
|
||||
}
|
||||
erase_addr = provision_start_addr;
|
||||
while (erase_addr < (last_addr - bottom_addr)) {
|
||||
status = iap_bd.erase(erase_addr, iap_bd.get_erase_size(erase_addr));
|
||||
if (0 != status) {
|
||||
printf("Error : iap erase failed.\r\n");
|
||||
iap_bd.deinit();
|
||||
return -1;
|
||||
}
|
||||
erase_addr += iap_bd.get_erase_size(erase_addr);
|
||||
}
|
||||
program_addr = provision_start_addr;
|
||||
while (size > 0) {
|
||||
status = iap_bd.program(&buffer[program_addr - provision_start_addr], program_addr, iap_bd.get_program_size());
|
||||
if (0 != status) {
|
||||
printf("Error : iap program failed.\r\n");
|
||||
iap_bd.deinit();
|
||||
return -1;
|
||||
}
|
||||
program_addr += iap_bd.get_program_size();
|
||||
size -= iap_bd.get_program_size();
|
||||
}
|
||||
status = iap_bd.deinit();
|
||||
if (0 != status) {
|
||||
printf("Error : iap deinit failed.\r\n");
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t plat_get_secure_flash_provision_info(uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
#if COMPONENT_FLASHIAP
|
||||
#if (MBED_CONF_FLASHIAP_BLOCK_DEVICE_SIZE == 0) && (MBED_CONF_FLASHIAP_BLOCK_DEVICE_BASE_ADDRESS == 0xFFFFFFFF)
|
||||
int status;
|
||||
uint32_t actual_size = 0;
|
||||
uint32_t bottom_addr, provision_start_addr, last_addr, read_addr;
|
||||
|
||||
mbed::FlashIAP flash;
|
||||
status = flash.init();
|
||||
if (0 != status) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Find the start of first sector after text area
|
||||
bottom_addr = align_up(FLASHIAP_APP_ROM_END_ADDR, flash.get_sector_size(FLASHIAP_APP_ROM_END_ADDR));
|
||||
last_addr = flash.get_flash_start() + flash.get_flash_size();
|
||||
status = flash.deinit();
|
||||
if (0 != status) {
|
||||
return -1;
|
||||
}
|
||||
FlashIAPBlockDevice iap_bd(bottom_addr, last_addr - bottom_addr);
|
||||
#else
|
||||
FlashIAPBlockDevice iap_bd;
|
||||
#endif
|
||||
|
||||
provision_start_addr = last_addr - 1;
|
||||
while (actual_size < PROVISION_INFO_SIZE) {
|
||||
provision_start_addr -= flash.get_sector_size(provision_start_addr);
|
||||
actual_size += flash.get_sector_size(provision_start_addr);
|
||||
}
|
||||
if ((provision_start_addr + 1) < bottom_addr) {
|
||||
return -1;
|
||||
}
|
||||
provision_start_addr = provision_start_addr - bottom_addr + 1;
|
||||
|
||||
status = iap_bd.init();
|
||||
if (0 != status) {
|
||||
printf("Error : iap init failed.\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
read_addr = provision_start_addr;
|
||||
while (size > 0) {
|
||||
status = iap_bd.read(&buffer[read_addr - provision_start_addr], read_addr, iap_bd.get_read_size());
|
||||
if (0 != status) {
|
||||
printf("Error : iap read failed.\r\n");
|
||||
iap_bd.deinit();
|
||||
return -1;
|
||||
}
|
||||
read_addr += iap_bd.get_read_size();
|
||||
size -= iap_bd.get_read_size();
|
||||
}
|
||||
|
||||
status = iap_bd.deinit();
|
||||
if (0 != status) {
|
||||
printf("Error : iap deinit failed.\r\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,540 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* 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 "SecureFBlockDevice.h"
|
||||
#include "rtos/ThisThread.h"
|
||||
#include "mbed_critical.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "mbed_trace.h"
|
||||
|
||||
#include "../spi_nor_flash/spi_nor.h"
|
||||
#include "../TG424_3/JEDEC_security_HAL/include/error.h"
|
||||
#include "../TG424_3/JEDEC_security_HAL/include/jedec_defs.h"
|
||||
#include "../TG424_3/JEDEC_security_HAL/jedec_security_hal.h"
|
||||
#include "../TG424_3/vendor_impl/vendor_secureflash.h"
|
||||
|
||||
#define TRACE_GROUP "SECUREF"
|
||||
using namespace std::chrono;
|
||||
using namespace mbed;
|
||||
|
||||
// Status Register Bits
|
||||
#define SPIF_STATUS_BIT_WIP 0x1 //Write In Progress
|
||||
#define SPIF_STATUS_BIT_WEL 0x2 // Write Enable Latch
|
||||
|
||||
mbed::SPI *SecureFBlockDevice::_spi;
|
||||
// Mutex is used for some SPI Driver commands that must be done sequentially with no other commands in between
|
||||
// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
|
||||
SingletonPtr<PlatformMutex> SecureFBlockDevice::_mutex;
|
||||
|
||||
//**************************
|
||||
// SECUREF Block Device APIs
|
||||
//**************************
|
||||
SecureFBlockDevice::SecureFBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName csel, int freq)
|
||||
:
|
||||
_mosi(mosi), _miso(miso), _sclk(sclk), _csel(csel), _freq(freq),
|
||||
_is_initialized(false)
|
||||
{}
|
||||
|
||||
int SecureFBlockDevice::init()
|
||||
{
|
||||
int status = SECUREF_BD_ERROR_OK;
|
||||
|
||||
_mutex->lock();
|
||||
|
||||
if (!_is_initialized) {
|
||||
_init_ref_count = 0;
|
||||
}
|
||||
|
||||
_init_ref_count++;
|
||||
|
||||
if (_init_ref_count != 1) {
|
||||
goto exit_point;
|
||||
}
|
||||
memset(&_secureflash, 0x00, sizeof (secureflash_t));
|
||||
|
||||
_spi = new (std::nothrow) mbed::SPI(_mosi, _miso, _sclk, _csel, use_gpio_ssel);
|
||||
if (0 == _spi) {
|
||||
tr_error("Allocation of mbed::SPI failed");
|
||||
goto exit_point;
|
||||
}
|
||||
if (SECUREF_BD_ERROR_OK != _spi_set_frequency(_freq)) {
|
||||
tr_error("SPI Set Frequency Failed");
|
||||
goto exit_point;
|
||||
}
|
||||
if (0 != spi_nor_init(_spi_read, _spi_write)) {
|
||||
status = SECUREF_BD_ERROR_DEVICE_ERROR;
|
||||
goto exit_point;
|
||||
}
|
||||
// Soft Reset
|
||||
if (0 != _reset_flash_mem()) {
|
||||
tr_error("init - Unable to initialize flash memory, tests failed");
|
||||
status = SECUREF_BD_ERROR_DEVICE_ERROR;
|
||||
goto exit_point;
|
||||
} else {
|
||||
tr_debug("Initialize flash memory OK");
|
||||
}
|
||||
// Synchronize Device
|
||||
if (0 != spi_nor_polling_for_wr_ready()) {
|
||||
tr_error("init - spi_nor_polling_for_wr_ready Failed");
|
||||
status = SECUREF_BD_ERROR_READY_FAILED;
|
||||
goto exit_point;
|
||||
}
|
||||
tr_debug("Probe secure flash");
|
||||
status = _probe();
|
||||
if (SECUREF_BD_ERROR_OK != status) {
|
||||
goto exit_point;
|
||||
}
|
||||
#ifdef SECUREFLASH_PROVISION
|
||||
tr_debug("Provision the secure flash");
|
||||
status = _secureflash.flash_info.vendor_provisioning_op->perform_and_verify(_secureflash.flash_info.vendor_ctx,
|
||||
NULL, 0);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_PROVISION_FLASH;
|
||||
goto exit_point;
|
||||
}
|
||||
#endif /* SECUREFLASH_PROVISION */
|
||||
tr_debug("Get the applicaition information");
|
||||
status = _secureflash_get_app_info();
|
||||
if (SECUREF_BD_ERROR_OK != status) {
|
||||
goto exit_point;
|
||||
}
|
||||
tr_debug("Jedect secure init");
|
||||
status = jedec_secure_init(SECUREFLASH_AUTHEN_KEY_ID);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_DEVICE_ERROR;
|
||||
goto exit_point;
|
||||
}
|
||||
_is_initialized = true;
|
||||
tr_debug("Init successful");
|
||||
exit_point:
|
||||
if (false == _is_initialized && 0 != _spi) {
|
||||
delete _spi;
|
||||
}
|
||||
_mutex->unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::_probe()
|
||||
{
|
||||
uint8_t vendor_device_ids[4];
|
||||
uint32_t data_length = 3;
|
||||
|
||||
// Read Manufacturer ID (1byte), and Device ID (2bytes)
|
||||
if (0 != spi_nor_read_id(vendor_device_ids, data_length)) {
|
||||
tr_error("Read Vendor ID Failed");
|
||||
return SECUREF_BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
tr_debug("Vendor device ID = 0x%x 0x%x 0x%x", vendor_device_ids[0], vendor_device_ids[1], vendor_device_ids[2]);
|
||||
|
||||
if (0 != _find_flash_info(vendor_device_ids)) {
|
||||
return SECUREF_BD_ERROR_DEVICE_UNSUPPORT;
|
||||
}
|
||||
return SECUREF_BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::_find_flash_info(uint8_t *id)
|
||||
{
|
||||
for (uint8_t i = 0; i < sizeof(flash_info); i++) {
|
||||
if (!memcmp(id, flash_info[i]->id, flash_info[i]->id_len)) {
|
||||
jedec_set_vendor(flash_info[i]->vendor_security_op,
|
||||
flash_info[i]->crypto_wrapper,
|
||||
flash_info[i]->vendor_ctx);
|
||||
flash_info[i]->crypto_wrapper->init();
|
||||
memcpy(&_secureflash.flash_info, flash_info[i], sizeof(secure_flash_info_t));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::_secureflash_get_app_info()
|
||||
{
|
||||
int status = JEDEC_ERROR_NONE;
|
||||
uint32_t actual_size;
|
||||
vendor_provisioning_op_t *provision_op = _secureflash.flash_info.vendor_provisioning_op;
|
||||
|
||||
status = provision_op->provision_item_get_data(_secureflash.flash_info.vendor_ctx,
|
||||
ITEM_APP_INFO,
|
||||
(uint8_t *)_secureflash.app_info.app_data,
|
||||
sizeof(_secureflash.app_info.app_data),
|
||||
&_secureflash.app_info.num,
|
||||
&actual_size);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
return SECUREF_BD_ERROR_GET_PROVISION;
|
||||
}
|
||||
return SECUREF_BD_ERROR_OK;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::deinit()
|
||||
{
|
||||
securef_bd_error status = SECUREF_BD_ERROR_OK;
|
||||
|
||||
_mutex->lock();
|
||||
if (!_is_initialized) {
|
||||
_init_ref_count = 0;
|
||||
goto exit_point;
|
||||
}
|
||||
_init_ref_count--;
|
||||
|
||||
if (_init_ref_count) {
|
||||
goto exit_point;
|
||||
}
|
||||
_is_initialized = false;
|
||||
|
||||
exit_point:
|
||||
if (false == _is_initialized && 0 != _spi) {
|
||||
delete _spi;
|
||||
}
|
||||
_mutex->unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::_spi_read(uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len)
|
||||
{
|
||||
_spi->select();
|
||||
|
||||
// Write/Read Data
|
||||
for (uint32_t i = 0; i < tx_len; i++) {
|
||||
_spi->write(tx_buf[i]);
|
||||
}
|
||||
for (uint32_t i = 0; i < rx_len; i++) {
|
||||
rx_buf[i] = _spi->write(0);
|
||||
}
|
||||
|
||||
_spi->deselect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::_spi_write(uint8_t *tx_buf, uint32_t tx_len)
|
||||
{
|
||||
_spi->select();
|
||||
|
||||
// Write Data
|
||||
for (uint32_t i = 0; i < tx_len; i++) {
|
||||
_spi->write(tx_buf[i]);
|
||||
}
|
||||
|
||||
_spi->deselect();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::erase(bd_addr_t addr, bd_size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
app_data_t *SecureFBlockDevice::_query_app_info(mbed::bd_addr_t addr, int app_id)
|
||||
{
|
||||
uint8_t zone_id = (uint8_t)(addr / SecureFBlockDevice::secure_zone_size());
|
||||
|
||||
for (int i = 0; i < _secureflash.app_info.num; i++) {
|
||||
if ((_secureflash.app_info.app_data[i].app_id == app_id) &&
|
||||
(_secureflash.app_info.app_data[i].zone_id == zone_id)) {
|
||||
return &(_secureflash.app_info.app_data[i]);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::secure_read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id)
|
||||
{
|
||||
int status = SECUREF_BD_ERROR_OK;
|
||||
app_data_t *app_data;
|
||||
uint32_t session_key_id, actual_read_size, offset, chunk, read_size = get_read_size();
|
||||
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
if (((uint32_t)(addr + size)) > SecureFBlockDevice::size()) {
|
||||
return SECUREF_BD_ERROR_INVALID_PGM_PARAMS;
|
||||
}
|
||||
_mutex->lock();
|
||||
app_data = _query_app_info(addr, app_id);
|
||||
if (NULL == app_data) {
|
||||
status = SECUREF_BD_ERROR_ILLEGAL_ACCESS;
|
||||
goto secure_read_exit_point;
|
||||
}
|
||||
status = jedec_create_session(app_data->key_id, 0, &session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_CREATE_SESSION;
|
||||
goto secure_read_exit_point;
|
||||
}
|
||||
while (size > 0) {
|
||||
offset = addr % read_size;
|
||||
chunk = (offset + size < read_size) ? size : (read_size - offset);
|
||||
status = jedec_secure_read(addr, (uint8_t *)buffer, chunk, session_key_id, &actual_read_size);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_SECURE_READ;
|
||||
goto secure_read_exit_point;
|
||||
}
|
||||
size -= chunk;
|
||||
addr += chunk;
|
||||
buffer += chunk;
|
||||
}
|
||||
status = jedec_terminate_session(session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_TERMINATE_SESSION;
|
||||
goto secure_read_exit_point;
|
||||
}
|
||||
secure_read_exit_point:
|
||||
_mutex->unlock();
|
||||
return status;
|
||||
}
|
||||
int SecureFBlockDevice::secure_program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id)
|
||||
{
|
||||
int status = SECUREF_BD_ERROR_OK;
|
||||
uint32_t session_key_id;
|
||||
app_data_t *app_data;
|
||||
uint32_t actual_program_size, chunk, offset, pgm_size = get_program_size();
|
||||
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (((uint32_t)(addr + size)) > SecureFBlockDevice::size()) {
|
||||
return SECUREF_BD_ERROR_INVALID_PGM_PARAMS;
|
||||
}
|
||||
_mutex->lock();
|
||||
app_data = _query_app_info(addr, app_id);
|
||||
if (NULL == app_data) {
|
||||
status = SECUREF_BD_ERROR_ILLEGAL_ACCESS;
|
||||
goto secure_program_exit_point;
|
||||
}
|
||||
status = jedec_create_session(app_data->key_id, 0, &session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_CREATE_SESSION;
|
||||
goto secure_program_exit_point;
|
||||
}
|
||||
while (size > 0) {
|
||||
offset = addr % pgm_size;
|
||||
chunk = (offset + size < pgm_size) ? size : (pgm_size - offset);
|
||||
status = jedec_secure_program(addr, (uint8_t *)buffer, chunk, session_key_id, &actual_program_size);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_SECURE_PROGRAM;
|
||||
goto secure_program_exit_point;
|
||||
}
|
||||
size -= chunk;
|
||||
addr += chunk;
|
||||
buffer += chunk;
|
||||
}
|
||||
status = jedec_terminate_session(session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_TERMINATE_SESSION;
|
||||
goto secure_program_exit_point;
|
||||
}
|
||||
secure_program_exit_point:
|
||||
_mutex->unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::secure_erase(mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id)
|
||||
{
|
||||
int status = SECUREF_BD_ERROR_OK;
|
||||
app_data_t *app_data;
|
||||
uint32_t session_key_id, ers_size = get_erase_size();
|
||||
|
||||
if (!_is_initialized) {
|
||||
return BD_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
if (((uint32_t)(addr + size)) > SecureFBlockDevice::size()) {
|
||||
return SECUREF_BD_ERROR_INVALID_ERASE_PARAMS;
|
||||
}
|
||||
if ((addr % ers_size) || (size % ers_size)) {
|
||||
return SECUREF_BD_ERROR_INVALID_ERASE_PARAMS;
|
||||
}
|
||||
_mutex->lock();
|
||||
app_data = _query_app_info(addr, app_id);
|
||||
if (NULL == app_data) {
|
||||
status = SECUREF_BD_ERROR_ILLEGAL_ACCESS;
|
||||
goto secure_erase_exit_point;
|
||||
}
|
||||
status = jedec_create_session(app_data->key_id, 0, &session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_CREATE_SESSION;
|
||||
goto secure_erase_exit_point;
|
||||
}
|
||||
while (size > 0) {
|
||||
status = jedec_secure_erase((uint32_t)addr, ers_size, session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_SECURE_ERASE;
|
||||
goto secure_erase_exit_point;
|
||||
}
|
||||
size -= ers_size;
|
||||
addr += ers_size;
|
||||
}
|
||||
status = jedec_terminate_session(session_key_id);
|
||||
if (JEDEC_ERROR_NONE != status) {
|
||||
status = SECUREF_BD_ERROR_TERMINATE_SESSION;
|
||||
goto secure_erase_exit_point;
|
||||
}
|
||||
secure_erase_exit_point:
|
||||
_mutex->unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
bd_size_t SecureFBlockDevice::get_read_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
return _secureflash.flash_info.flash_profile->architecture.secure_read_size;
|
||||
}
|
||||
|
||||
bd_size_t SecureFBlockDevice::get_program_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
return _secureflash.flash_info.flash_profile->architecture.secure_program_size;
|
||||
}
|
||||
|
||||
bd_size_t SecureFBlockDevice::get_erase_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
return _secureflash.flash_info.flash_profile->architecture.regions_min_secure_erase_size;
|
||||
}
|
||||
|
||||
// Find minimal erase size supported by the region to which the address belongs to
|
||||
bd_size_t SecureFBlockDevice::get_erase_size(bd_addr_t addr) const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
return _secureflash.flash_info.flash_profile->architecture.regions_min_secure_erase_size;
|
||||
}
|
||||
bd_size_t SecureFBlockDevice::secure_zone_number() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
return _secureflash.flash_info.flash_profile->architecture.secure_zone_number;
|
||||
}
|
||||
|
||||
bd_size_t SecureFBlockDevice::secure_zone_size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
return _secureflash.flash_info.flash_profile->architecture.secure_zone_size;
|
||||
}
|
||||
|
||||
bd_size_t SecureFBlockDevice::size() const
|
||||
{
|
||||
if (!_is_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _secureflash.flash_info.flash_profile->architecture.secure_zone_total_size;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::get_erase_value() const
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
const char *SecureFBlockDevice::get_type() const
|
||||
{
|
||||
return "SECUREF";
|
||||
}
|
||||
|
||||
/***************************************************/
|
||||
/*********** SPI Driver API Functions **************/
|
||||
/***************************************************/
|
||||
securef_bd_error SecureFBlockDevice::_spi_set_frequency(int freq)
|
||||
{
|
||||
_spi->frequency(freq);
|
||||
return SECUREF_BD_ERROR_OK;
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/********** SFDP Parsing and Detection Functions *********/
|
||||
/*********************************************************/
|
||||
int SecureFBlockDevice::_reset_flash_mem()
|
||||
{
|
||||
// Perform Soft Reset of the Device prior to initialization
|
||||
int status = 0;
|
||||
uint8_t status_value[2] = {0};
|
||||
tr_info("_reset_flash_mem:");
|
||||
// Read the Status Register from device
|
||||
if (0 == spi_nor_read_sr(status_value, 1)) {
|
||||
// store received values in status_value
|
||||
tr_debug("Reading Status Register Success: value = 0x%x", (int)status_value[0]);
|
||||
} else {
|
||||
tr_error("Reading Status Register failed");
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (0 == status) {
|
||||
// Send Reset Enable
|
||||
if (0 == spi_nor_reset_enable()) {
|
||||
// store received values in status_value
|
||||
tr_debug("Sending RSTEN Success");
|
||||
} else {
|
||||
tr_error("Sending RSTEN failed");
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (0 == status) {
|
||||
// Send Reset
|
||||
if (0 == spi_nor_reset()) {
|
||||
// store received values in status_value
|
||||
tr_debug("Sending RST Success");
|
||||
} else {
|
||||
tr_error("Sending RST failed");
|
||||
status = -1;
|
||||
}
|
||||
if (0 != spi_nor_polling_for_wr_ready()) {
|
||||
tr_error("Device not ready, write failed");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int SecureFBlockDevice::_handle_vendor_quirks()
|
||||
{
|
||||
uint8_t vendor_device_ids[4];
|
||||
size_t data_length = 3;
|
||||
|
||||
// Read Manufacturer ID (1byte), and Device ID (2bytes)
|
||||
if (0 != spi_nor_read_id(vendor_device_ids, data_length)) {
|
||||
tr_error("Read Vendor ID Failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
tr_debug("Vendor device ID = 0x%x 0x%x 0x%x", vendor_device_ids[0], vendor_device_ids[1], vendor_device_ids[2]);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "spi_nor.h"
|
||||
|
||||
#define STD_INST_PP 0x02
|
||||
#define STD_INST_READ 0x03
|
||||
#define STD_INST_ERASE_SECTOR 0x20
|
||||
#define STD_INST_RDSCUR 0x2B
|
||||
#define STD_INST_RDCR 0x15
|
||||
#define STD_INST_RDCR2 0x71
|
||||
#define STD_INST_RDSR 0x05
|
||||
#define STD_INST_RDID 0x9F
|
||||
|
||||
#define STD_INST_RSTEN 0x66
|
||||
#define STD_INST_RST 0x99
|
||||
#define STD_INST_RSTQPI 0xF5
|
||||
|
||||
#define STD_INST_WREN 0x06
|
||||
#define STD_INST_FREAD 0x0B
|
||||
#define STD_INST_ENSO 0xB1
|
||||
#define STD_INST_EXSO 0xC1
|
||||
|
||||
/* status register definition */
|
||||
#define SR_WIP 0x01
|
||||
#define SR_WEL 0x02
|
||||
#define SR_QE 0x40 /* Quad-IO enable bit */
|
||||
#define SR_BP0 0x04 /* Block protect 0 */
|
||||
#define SR_BP1 0x08 /* Block protect 1 */
|
||||
#define SR_BP2 0x10 /* Block protect 2 */
|
||||
#define SR_BP3 0x20 /* Block protect 3 */
|
||||
#define SR_BP_BIT_OFFSET 2 /* Offset to Block protect 0 */
|
||||
#define SR_BP_BIT_MASK (SR_BP3 | SR_BP2 | SR_BP1 | SR_BP0)
|
||||
#define SR_SRWD 0x80 /* SR write protect */
|
||||
|
||||
#define SCUR_ORDY 0x10 /* Security packet output ready bit */
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FAILURE -1
|
||||
#define BUFFER_SIZE 0x132
|
||||
#define MAX_POLLING_TIMES 1000
|
||||
|
||||
static spi_nor_t spi_nor = {};
|
||||
|
||||
static void wait_for_us(uint32_t microsec)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static void wait_for_ms(uint32_t millisec)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
static void cmd_packing(nor_cmd_packet_t *cmd_packet)
|
||||
{
|
||||
uint32_t send_packet_size = 0;
|
||||
|
||||
cmd_packet->cmd_buffer.tx_buf[0] = cmd_packet->cmd;
|
||||
send_packet_size++;
|
||||
if (cmd_packet->addr_len > 0) {
|
||||
memcpy(&cmd_packet->cmd_buffer.tx_buf[send_packet_size], cmd_packet->addr, cmd_packet->addr_len);
|
||||
send_packet_size += cmd_packet->addr_len;
|
||||
}
|
||||
if (cmd_packet->dummy_len > 0) {
|
||||
memset(&cmd_packet->cmd_buffer.tx_buf[send_packet_size], 0xFF, cmd_packet->dummy_len);
|
||||
send_packet_size += cmd_packet->dummy_len;
|
||||
}
|
||||
if (cmd_packet->data != NULL) {
|
||||
memcpy(&cmd_packet->cmd_buffer.tx_buf[send_packet_size], cmd_packet->data, cmd_packet->data_len);
|
||||
send_packet_size += cmd_packet->data_len;
|
||||
}
|
||||
cmd_packet->cmd_buffer.tx_len = send_packet_size;
|
||||
}
|
||||
|
||||
int32_t spi_read(uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len)
|
||||
{
|
||||
spi_nor.read(tx_buf, tx_len, rx_buf, rx_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_write(uint8_t *tx_buf, uint32_t tx_len)
|
||||
{
|
||||
spi_nor.write(tx_buf, tx_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_reset_enable(void)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_RSTEN;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.write(spi_nor.cmd_packet.cmd_buffer.tx_buf, spi_nor.cmd_packet.cmd_buffer.tx_len);
|
||||
}
|
||||
|
||||
int32_t spi_nor_reset(void)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_RST;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.write(spi_nor.cmd_packet.cmd_buffer.tx_buf, spi_nor.cmd_packet.cmd_buffer.tx_len);
|
||||
|
||||
}
|
||||
|
||||
int32_t spi_nor_write_enable(void)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_WREN;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.write(spi_nor.cmd_packet.cmd_buffer.tx_buf, spi_nor.cmd_packet.cmd_buffer.tx_len);
|
||||
}
|
||||
|
||||
int32_t spi_nor_write_disable(void)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_read(uint8_t *buffer, uint32_t addr, uint32_t size)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_program(uint8_t *buffer, uint32_t addr, uint32_t size)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_erase(uint32_t addr, uint32_t size)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_read_id(uint8_t *id, uint32_t size)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_RDID;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.read(spi_nor.cmd_packet.cmd_buffer.tx_buf,
|
||||
spi_nor.cmd_packet.cmd_buffer.tx_len,
|
||||
id, size);
|
||||
}
|
||||
|
||||
int32_t spi_nor_read_sr(uint8_t *sr, uint32_t size)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_RDSR;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.read(spi_nor.cmd_packet.cmd_buffer.tx_buf,
|
||||
spi_nor.cmd_packet.cmd_buffer.tx_len,
|
||||
sr, size);
|
||||
}
|
||||
|
||||
int32_t spi_nor_read_cr(uint8_t *cr, uint32_t size)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_RDCR;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.read(spi_nor.cmd_packet.cmd_buffer.tx_buf,
|
||||
spi_nor.cmd_packet.cmd_buffer.tx_len,
|
||||
cr, size);
|
||||
}
|
||||
|
||||
int32_t spi_nor_read_cr2(uint8_t *cr, uint32_t size)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_read_scur(uint8_t *scur, uint32_t size)
|
||||
{
|
||||
spi_nor.cmd_packet.cmd = STD_INST_RDSCUR;
|
||||
spi_nor.cmd_packet.addr_len = 0;
|
||||
spi_nor.cmd_packet.dummy_len = 0;
|
||||
spi_nor.cmd_packet.data = NULL;
|
||||
cmd_packing(&spi_nor.cmd_packet);
|
||||
return spi_nor.read(spi_nor.cmd_packet.cmd_buffer.tx_buf,
|
||||
spi_nor.cmd_packet.cmd_buffer.tx_len,
|
||||
scur, size);
|
||||
}
|
||||
|
||||
int32_t spi_nor_enter_secured_OTP(void)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_exit_secured_OTP(void)
|
||||
{
|
||||
//TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_software_reset(void)
|
||||
{
|
||||
if (spi_nor_reset_enable() != SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
if (spi_nor_reset() != SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
wait_for_ms(1);//stm32l562 hal driver not support us delay
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_polling_for_wr_ready(void)
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
uint8_t status_reg;
|
||||
/* Polling for secure Flash ready for program */
|
||||
do {
|
||||
cnt++;
|
||||
if (spi_nor_read_sr(&status_reg, 1) != SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
wait_for_ms(1);
|
||||
} while ((status_reg & SR_WIP) && (cnt < MAX_POLLING_TIMES));
|
||||
|
||||
if (cnt >= MAX_POLLING_TIMES) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int32_t spi_nor_polling_for_out_ready(void)
|
||||
{
|
||||
uint32_t cnt = 0;
|
||||
uint8_t status_reg, scur_reg;
|
||||
|
||||
/* Polling for secure Flash ready for program */
|
||||
do {
|
||||
cnt++;
|
||||
if (spi_nor_read_scur(&scur_reg, 1) != SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
if (spi_nor_read_sr(&status_reg, 1) != SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
wait_for_ms(1);
|
||||
} while (((status_reg & SR_WIP) || !(scur_reg & SCUR_ORDY)) && (cnt < MAX_POLLING_TIMES));
|
||||
|
||||
if (cnt >= MAX_POLLING_TIMES) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t spi_nor_init(spi_read_t spi_read, spi_write_t spi_write)
|
||||
{
|
||||
if (spi_read == NULL || spi_write == NULL) {
|
||||
printf("ERROR: spi_ctx == NULL(%08X, %08X)\r\n", spi_read, spi_write);
|
||||
}
|
||||
spi_nor.read = spi_read;
|
||||
spi_nor.write = spi_write;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2022-2023 Macronix International Co. LTD. 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.
|
||||
*/
|
||||
#ifndef _SPI_NOR_H_
|
||||
#define _SPI_NOR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_ADDR_LEN 4
|
||||
#define MAX_ID_LEN 6
|
||||
#define BUFFER_SIZE 0x132
|
||||
|
||||
typedef int (*spi_read_t)(uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len);
|
||||
typedef int (*spi_write_t)(uint8_t *tx_buf, uint32_t tx_len);
|
||||
|
||||
struct nor_cmd_packet {
|
||||
uint8_t cmd;
|
||||
uint8_t addr[MAX_ADDR_LEN];
|
||||
uint8_t addr_len;
|
||||
uint8_t dummy_len;
|
||||
uint8_t *data;
|
||||
uint32_t data_len;
|
||||
struct {
|
||||
uint8_t tx_buf[BUFFER_SIZE];
|
||||
uint32_t tx_len;
|
||||
uint8_t rx_buf[BUFFER_SIZE];
|
||||
uint32_t rx_len;
|
||||
} cmd_buffer;
|
||||
};
|
||||
|
||||
struct spi_nor {
|
||||
uint8_t id[MAX_ID_LEN];
|
||||
uint8_t read_dummy_cycle;
|
||||
struct nor_cmd_packet cmd_packet;
|
||||
spi_read_t read;
|
||||
spi_write_t write;
|
||||
};
|
||||
|
||||
typedef struct nor_cmd_packet nor_cmd_packet_t;
|
||||
typedef struct spi_nor spi_nor_t;
|
||||
|
||||
int32_t spi_read(uint8_t *tx_buf, uint32_t tx_len, uint8_t *rx_buf, uint32_t rx_len);
|
||||
int32_t spi_write(uint8_t *tx_buf, uint32_t tx_len);
|
||||
|
||||
int32_t spi_nor_init(spi_read_t spi_read, spi_write_t spi_write);
|
||||
/**
|
||||
* \brief Enable software reset.
|
||||
*
|
||||
* \return: 0 on success, -1 if not
|
||||
*/
|
||||
int32_t spi_nor_reset_enable(void);
|
||||
/**
|
||||
* \brief Perform a software reset.
|
||||
*
|
||||
* \return: 0 on success, -1 if not
|
||||
*/
|
||||
int32_t spi_nor_reset(void);
|
||||
/**
|
||||
* \brief Set write enable latch.
|
||||
*
|
||||
* \return: 0 on success, -1 if not
|
||||
*/
|
||||
int32_t spi_nor_write_enable(void);
|
||||
/**
|
||||
* \brief Send write disable instruction to the chip.
|
||||
*
|
||||
* \return: 0 on success, -1 if not
|
||||
*/
|
||||
int32_t spi_nor_write_disable(void);
|
||||
/**
|
||||
* \brief Read data from flash.
|
||||
* \param[in] buffer pointer to destination buffer
|
||||
* \param[in] addr Address to read from
|
||||
* \param[in] size Number of bytes to read
|
||||
* \return: number of bytes read successfully, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_read(uint8_t *buffer, uint32_t addr, uint32_t size);
|
||||
/**
|
||||
* \brief Write data to flash.
|
||||
* \param[in] buffer Pointer to source buffer
|
||||
* \param[in] addr Address to write to
|
||||
* \param[in] size Number of bytes to write
|
||||
* \return: number of bytes written successfully, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_program(uint8_t *buffer, uint32_t addr, uint32_t size);
|
||||
/**
|
||||
* \brief Erase an address range on the nor chip.
|
||||
* \param[in] addr Address to erase
|
||||
* \param[in] size Erase size
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_erase(uint32_t addr, uint32_t size);
|
||||
/**
|
||||
* \brief Read the JEDEC ID.
|
||||
* \param[in] id Pointer to buffer where the value of JEDEC ID will be written
|
||||
* \param[in] size ID size
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_read_id(uint8_t *id, uint32_t size);
|
||||
/**
|
||||
* \brief Read the status register.
|
||||
* \param[in] sr Pointer to buffer where the value of status register will be written
|
||||
* \param[in] size SR size
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_read_sr(uint8_t *sr, uint32_t size);
|
||||
/**
|
||||
* \brief Read the configuration register.
|
||||
* \param[in] cr Pointer to buffer where the value of configuration register will be written
|
||||
* \param[in] size CR size
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_read_cr(uint8_t *cr, uint32_t size);
|
||||
/**
|
||||
* \brief Read the security register.
|
||||
* \param[in] scur Pointer to buffer where the value of security register will be written
|
||||
* \param[in] size SCUR size
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_read_scur(uint8_t *scur, uint32_t size);
|
||||
/**
|
||||
* \brief Enter secured OTP.
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_enter_secured_OTP(void);
|
||||
/**
|
||||
* \brief Exit secured OTP.
|
||||
* \return: 0 on success, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_exit_secured_OTP(void);
|
||||
/**
|
||||
* \brief Polling for nor flash ready for program.
|
||||
*
|
||||
* \return: 0 if flash is ready for program, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_polling_for_wr_ready(void);
|
||||
/**
|
||||
* \brief Polling for nor flash ready for read.
|
||||
*
|
||||
* \return: 0 if flash is ready for read, -1 otherwise
|
||||
*/
|
||||
int32_t spi_nor_polling_for_out_ready(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SPI_NOR_H_ */
|
|
@ -139,6 +139,27 @@ public:
|
|||
return 0;
|
||||
}
|
||||
|
||||
virtual int secure_read(void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
virtual int secure_program(const void *buffer, mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
virtual int secure_erase(mbed::bd_addr_t addr, mbed::bd_size_t size, int app_id)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
virtual bd_size_t secure_zone_number() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual bd_size_t secure_zone_size() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Get the size of a readable block
|
||||
*
|
||||
* @return Size of a readable block in bytes
|
||||
|
|
|
@ -38,6 +38,10 @@ if("SPIF" IN_LIST MBED_TARGET_LABELS)
|
|||
list(APPEND mbed_blockdevice_libs mbed-storage-spif)
|
||||
endif()
|
||||
|
||||
if("SECUREF" IN_LIST MBED_TARGET_LABELS)
|
||||
list(APPEND mbed_blockdevice_libs mbed-storage-securef)
|
||||
endif()
|
||||
|
||||
mbed_greentea_add_test(
|
||||
TEST_NAME
|
||||
${TEST_TARGET}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "BufferedBlockDevice.h"
|
||||
#include "BlockDevice.h"
|
||||
#include <algorithm>
|
||||
#include "mx78_armor2_provision_example.h"
|
||||
|
||||
#if COMPONENT_SPIF
|
||||
#include "SPIFBlockDevice.h"
|
||||
|
@ -57,6 +58,10 @@
|
|||
#include "SPINANDBlockDevice.h"
|
||||
#endif
|
||||
|
||||
#if COMPONENT_SECUREF
|
||||
#include "SecureFBlockDevice.h"
|
||||
#endif
|
||||
|
||||
// Debug available
|
||||
#ifndef MODE_DEBUG
|
||||
#define MODE_DEBUG 0
|
||||
|
@ -97,10 +102,11 @@ enum bd_type {
|
|||
flashiap,
|
||||
ospif,
|
||||
spinand,
|
||||
securef,
|
||||
default_bd
|
||||
};
|
||||
|
||||
uint8_t bd_arr[6] = {0};
|
||||
uint8_t bd_arr[default_bd] = {0};
|
||||
|
||||
static uint8_t test_iteration = 0;
|
||||
|
||||
|
@ -238,6 +244,19 @@ static BlockDevice *get_bd_instance(uint8_t bd_type)
|
|||
|
||||
#endif
|
||||
return &default_bd;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case securef: {
|
||||
#if COMPONENT_SECUREF
|
||||
static SecureFBlockDevice default_bd(
|
||||
MBED_CONF_SECUREF_DRIVER_SPI_MOSI,
|
||||
MBED_CONF_SECUREF_DRIVER_SPI_MISO,
|
||||
MBED_CONF_SECUREF_DRIVER_SPI_CLK,
|
||||
MBED_CONF_SECUREF_DRIVER_SPI_CS,
|
||||
MBED_CONF_SECUREF_DRIVER_SPI_FREQ
|
||||
);
|
||||
return &default_bd;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
@ -273,16 +292,43 @@ void basic_erase_program_read_test(BlockDevice *block_device, bd_size_t block_si
|
|||
write_block[i_ind] = 0xff & rand();
|
||||
}
|
||||
// Write, sync, and read the block
|
||||
DEBUG_PRINTF("test %0*llx:%llu...\n", addrwidth, block, curr_block_size);
|
||||
DEBUG_PRINTF("test %llx:%llu...\n", addrwidth, block);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = block / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
err = block_device->erase(block, curr_block_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone %llx , SKIP!!!\n", block, access_zone_id);
|
||||
_mutex->unlock();
|
||||
return;
|
||||
}
|
||||
err = block_device->secure_erase(block, curr_block_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
err = block_device->program(write_block, block, block_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->secure_program(write_block, block, block_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
err = block_device->read(read_block, block, block_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->secure_read(read_block, block, block_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
|
||||
err = block_device->erase(block, curr_block_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
err = block_device->program(write_block, block, block_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
err = block_device->read(read_block, block, block_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
|
||||
// Check that the data was unmodified
|
||||
srand(seed);
|
||||
|
@ -406,6 +452,7 @@ void test_multi_threads()
|
|||
utest_printf("\nTest Multi Threaded Erase/Program/Read Starts..\n");
|
||||
|
||||
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
|
||||
TEST_SKIP_UNLESS_MESSAGE(strcmp(block_device->get_type(), "SECUREF"), "Secure Flash currently does not support this type of test.");
|
||||
|
||||
for (unsigned atr = 0; atr < sizeof(ATTRS) / sizeof(ATTRS[0]); atr++) {
|
||||
static const char *prefixes[] = {"", "k", "M", "G"};
|
||||
|
@ -575,44 +622,94 @@ void test_erase_functionality()
|
|||
uint8_t *out_data_buf = new (std::nothrow) uint8_t[data_buf_size];
|
||||
TEST_SKIP_UNLESS_MESSAGE(out_data_buf != NULL, "Not enough memory for test");
|
||||
|
||||
// First must Erase given memory region
|
||||
utest_printf("erasing given memory region\n");
|
||||
int err = block_device->erase(start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = start_address / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
// Write random data to selected region to make sure data is not accidentally set to "erased" value.
|
||||
// With this pre-write, the test case will fail even if block_device->erase() is broken.
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
data_buf[i] = (uint8_t) rand();
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// First must Erase given memory region
|
||||
utest_printf("erasing given memory region\n");
|
||||
int err = block_device->secure_erase(start_address, data_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Write random data to selected region to make sure data is not accidentally set to "erased" value.
|
||||
// With this pre-write, the test case will fail even if block_device->erase() is broken.
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
data_buf[i] = (uint8_t) rand();
|
||||
}
|
||||
|
||||
utest_printf("writing given memory region\n");
|
||||
err = block_device->secure_program((const void *)data_buf, start_address, data_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Read written memory region to verify it contains information
|
||||
memset(out_data_buf, 0, data_buf_size);
|
||||
utest_printf("reading written memory region\n");
|
||||
err = block_device->secure_read((void *)out_data_buf, start_address, data_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Verify erased memory region
|
||||
utest_printf("verifying written memory region\n");
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
TEST_ASSERT_EQUAL(out_data_buf[i], data_buf[i]);
|
||||
}
|
||||
|
||||
// Erase given memory region
|
||||
utest_printf("erasing written memory region\n");
|
||||
err = block_device->secure_erase(start_address, data_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Read erased memory region
|
||||
utest_printf("reading erased memory region\n");
|
||||
memset(out_data_buf, 0, data_buf_size);
|
||||
err = block_device->secure_read((void *)out_data_buf, start_address, data_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
// First must Erase given memory region
|
||||
utest_printf("erasing given memory region\n");
|
||||
int err = block_device->erase(start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Write random data to selected region to make sure data is not accidentally set to "erased" value.
|
||||
// With this pre-write, the test case will fail even if block_device->erase() is broken.
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
data_buf[i] = (uint8_t) rand();
|
||||
}
|
||||
|
||||
utest_printf("writing given memory region\n");
|
||||
err = block_device->program((const void *)data_buf, start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Read written memory region to verify it contains information
|
||||
memset(out_data_buf, 0, data_buf_size);
|
||||
utest_printf("reading written memory region\n");
|
||||
err = block_device->read((void *)out_data_buf, start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Verify erased memory region
|
||||
utest_printf("verifying written memory region\n");
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
TEST_ASSERT_EQUAL(out_data_buf[i], data_buf[i]);
|
||||
}
|
||||
|
||||
// Erase given memory region
|
||||
utest_printf("erasing written memory region\n");
|
||||
err = block_device->erase(start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Read erased memory region
|
||||
utest_printf("reading erased memory region\n");
|
||||
memset(out_data_buf, 0, data_buf_size);
|
||||
err = block_device->read((void *)out_data_buf, start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
|
||||
utest_printf("writing given memory region\n");
|
||||
err = block_device->program((const void *)data_buf, start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Read written memory region to verify it contains information
|
||||
memset(out_data_buf, 0, data_buf_size);
|
||||
utest_printf("reading written memory region\n");
|
||||
err = block_device->read((void *)out_data_buf, start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Verify erased memory region
|
||||
utest_printf("verifying written memory region\n");
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
TEST_ASSERT_EQUAL(out_data_buf[i], data_buf[i]);
|
||||
}
|
||||
|
||||
// Erase given memory region
|
||||
utest_printf("erasing written memory region\n");
|
||||
err = block_device->erase(start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Read erased memory region
|
||||
utest_printf("reading erased memory region\n");
|
||||
memset(out_data_buf, 0, data_buf_size);
|
||||
err = block_device->read((void *)out_data_buf, start_address, data_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
|
||||
// Verify erased memory region
|
||||
utest_printf("verifying erased memory region\n");
|
||||
for (bd_size_t i = 0; i < data_buf_size; i++) {
|
||||
|
@ -637,6 +734,7 @@ void test_contiguous_erase_write_read()
|
|||
// 3. Return step 2 for whole erase region
|
||||
|
||||
// Test parameters
|
||||
int err = 0;
|
||||
bd_size_t program_size = block_device->get_program_size();
|
||||
TEST_ASSERT(program_size > 0);
|
||||
utest_printf("program_size=%" PRId64 "\n", program_size);
|
||||
|
@ -679,8 +777,27 @@ void test_contiguous_erase_write_read()
|
|||
|
||||
// Must Erase the whole region first
|
||||
utest_printf("erasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "\n", start_address, contiguous_erase_size);
|
||||
int err = block_device->erase(start_address, contiguous_erase_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = start_address / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone(%llu), SKIP!!!\n", start_address, access_zone_id);
|
||||
}
|
||||
err = block_device->secure_erase(start_address, contiguous_erase_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
int err = block_device->erase(start_address, contiguous_erase_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
|
||||
// Pre-fill the to-be-erased region. By pre-filling the region,
|
||||
// we can be sure the test will not pass if the erase doesn't work.
|
||||
|
@ -694,14 +811,54 @@ void test_contiguous_erase_write_read()
|
|||
}
|
||||
DEBUG_PRINTF("pre-filling memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "", start_address + offset,
|
||||
write_read_buf_size);
|
||||
err = block_device->program((const void *)write_read_buf, start_address + offset, write_read_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = start_address / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone(%llu), SKIP!!!\n", start_address, access_zone_id);
|
||||
continue;
|
||||
}
|
||||
DEBUG_PRINTF("Test secure_program in zone %d\n", valid_zone_id);
|
||||
err = block_device->secure_program((const void *)write_read_buf, start_address + offset, write_read_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
err = block_device->program((const void *)write_read_buf, start_address + offset, write_read_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
}
|
||||
|
||||
// Erase the whole region again
|
||||
utest_printf("erasing memory, from 0x%" PRIx64 " of size 0x%" PRIx64 "\n", start_address, contiguous_erase_size);
|
||||
err = block_device->erase(start_address, contiguous_erase_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = start_address / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone(%llu), SKIP!!!\n", start_address, access_zone_id);
|
||||
}
|
||||
err = block_device->secure_erase(start_address, contiguous_erase_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
err = block_device->erase(start_address, contiguous_erase_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
|
||||
// Loop through all write/read regions
|
||||
int region = 0;
|
||||
|
@ -718,13 +875,55 @@ void test_contiguous_erase_write_read()
|
|||
}
|
||||
|
||||
// Write test data
|
||||
err = block_device->program((const void *)write_read_buf, start_address, write_read_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = start_address / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone(%llu), SKIP!!!\n", start_address, access_zone_id);
|
||||
continue;
|
||||
}
|
||||
DEBUG_PRINTF("Test secure_program in zone %d\n", valid_zone_id);
|
||||
err = block_device->secure_program((const void *)write_read_buf, start_address, write_read_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
err = block_device->program((const void *)write_read_buf, start_address, write_read_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
|
||||
// Read test data
|
||||
memset(write_read_buf, 0, (size_t)write_read_buf_size);
|
||||
err = block_device->read(write_read_buf, start_address, write_read_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
if (!strcmp(block_device->get_type(), "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = start_address / block_device->secure_zone_size();
|
||||
int n;
|
||||
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone(%llu), SKIP!!!\n", start_address, access_zone_id);
|
||||
continue;
|
||||
}
|
||||
DEBUG_PRINTF("Test secure_read in zone %d\n", valid_zone_id);
|
||||
err = block_device->secure_read(write_read_buf, start_address, write_read_buf_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
} else {
|
||||
err = block_device->read(write_read_buf, start_address, write_read_buf_size);
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
}
|
||||
|
||||
// Verify read data
|
||||
srand(seed);
|
||||
|
@ -746,6 +945,7 @@ void test_program_read_small_data_sizes()
|
|||
utest_printf("\nTest program-read small data sizes, from 1 to 7 bytes..\n");
|
||||
|
||||
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
|
||||
TEST_SKIP_UNLESS_MESSAGE(strcmp(block_device->get_type(), "SECUREF"), "Secure Flash currently does not support this type of test.");
|
||||
|
||||
bd_size_t program_size = block_device->get_program_size();
|
||||
bd_size_t read_size = block_device->get_read_size();
|
||||
|
@ -803,6 +1003,7 @@ void test_unaligned_erase_blocks()
|
|||
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
|
||||
|
||||
TEST_SKIP_UNLESS_MESSAGE(block_device->get_erase_value() != -1, "block device has no erase functionality.");
|
||||
TEST_SKIP_UNLESS_MESSAGE(strcmp(block_device->get_type(), "SECUREF"), "Secure Flash currently does not support this type of test.");
|
||||
|
||||
bd_addr_t addr = 0;
|
||||
bd_size_t sector_erase_size = block_device->get_erase_size(addr);
|
||||
|
@ -856,6 +1057,7 @@ void test_deinit_bd()
|
|||
void test_write_deinit_init()
|
||||
{
|
||||
TEST_SKIP_UNLESS_MESSAGE(block_device != NULL, "no block device found.");
|
||||
const char *bd_type = block_device->get_type();
|
||||
// Determine start_address & stop_address
|
||||
bd_addr_t addr = sectors_addr[rand() % num_of_sectors];
|
||||
bd_size_t erase_size = block_device->get_erase_size(addr);
|
||||
|
@ -871,17 +1073,46 @@ void test_write_deinit_init()
|
|||
prog[j] = (uint8_t)'0' + i + j;
|
||||
}
|
||||
|
||||
int err;
|
||||
err = block_device->erase(addr, erase_size);
|
||||
TEST_ASSERT_EQUAL(err, 0);
|
||||
err = block_device->program(prog, addr, prog_size);
|
||||
TEST_ASSERT_EQUAL(err, 0);
|
||||
err = block_device->deinit();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->init();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->read(buf, addr, prog_size);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(prog, buf, prog_size));
|
||||
int err, n;
|
||||
if (!strcmp(bd_type, "SECUREF")) {
|
||||
uint32_t valid_app_id, valid_zone_id;
|
||||
bd_size_t access_zone_id = addr / block_device->secure_zone_size();
|
||||
|
||||
for (n = 0; n < AVAILABLE_PAIR_NUM; n++) {
|
||||
if (access_zone_id == app_zone_available_pair[n].secure_zone_id) {
|
||||
valid_app_id = app_zone_available_pair[n].app_id;
|
||||
valid_zone_id = app_zone_available_pair[n].secure_zone_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (AVAILABLE_PAIR_NUM == n) {
|
||||
utest_printf("Address %llx is not in the avaliable zone(%llu), SKIP!!!\n", addr, access_zone_id);
|
||||
continue;
|
||||
}
|
||||
err = block_device->secure_erase(addr, erase_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(err, 0);
|
||||
err = block_device->secure_program(prog, addr, prog_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(err, 0);
|
||||
err = block_device->deinit();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->init();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
// err = block_device->secure_read(buf, addr, prog_size, app_id);
|
||||
err = block_device->secure_read(buf, addr, prog_size, valid_app_id);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(prog, buf, prog_size));
|
||||
|
||||
} else {
|
||||
err = block_device->erase(addr, erase_size);
|
||||
TEST_ASSERT_EQUAL(err, 0);
|
||||
err = block_device->program(prog, addr, prog_size);
|
||||
TEST_ASSERT_EQUAL(err, 0);
|
||||
err = block_device->deinit();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->init();
|
||||
TEST_ASSERT_EQUAL(0, err);
|
||||
err = block_device->read(buf, addr, prog_size);
|
||||
TEST_ASSERT_EQUAL(0, memcmp(prog, buf, prog_size));
|
||||
}
|
||||
}
|
||||
free(prog);
|
||||
free(buf);
|
||||
|
@ -911,6 +1142,8 @@ void test_get_type_functionality()
|
|||
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "FLASHIAP"));
|
||||
#elif COMPONENT_SPINAND
|
||||
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "SPINAND"));
|
||||
#elif COMPONENT_SECUREF
|
||||
TEST_ASSERT_EQUAL(0, strcmp(bd_type, "SECUREF"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -975,11 +1208,14 @@ int get_bd_count()
|
|||
#if COMPONENT_SPINAND
|
||||
bd_arr[count++] = spinand; //6
|
||||
#endif
|
||||
#if COMPONENT_SECUREF
|
||||
bd_arr[count++] = securef; //7
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const char *prefix[] = {"SPIF ", "QSPIF ", "DATAFLASH ", "SD ", "FLASHIAP ", "OSPIF ", "SPINAND ", "DEFAULT "};
|
||||
static const char *prefix[] = {"SPIF ", "QSPIF ", "DATAFLASH ", "SD ", "FLASHIAP ", "OSPIF ", "SPINAND ", "SECUREF ", "DEFAULT "};
|
||||
|
||||
int main()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef MBED_MX78_ARMOR2_PROVISION_EXAMPLE_H
|
||||
#define MBED_MX78_ARMOR2_PROVISION_EXAMPLE_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define AVAILABLE_PAIR_NUM 4
|
||||
typedef struct {
|
||||
uint32_t app_id;
|
||||
uint32_t secure_zone_id;
|
||||
} app_zone_pair_t;
|
||||
|
||||
const app_zone_pair_t app_zone_available_pair[AVAILABLE_PAIR_NUM] = {
|
||||
{0xFFFFFFFE, 0x00},
|
||||
{0xFFFFFFFD, 0x01},
|
||||
{0x00000BBA, 0x02},
|
||||
{0x00000BBE, 0x03},
|
||||
};
|
||||
|
||||
#endif /* MBED_MX78_ARMOR2_PROVISION_EXAMPLE_H */
|
|
@ -4573,6 +4573,9 @@
|
|||
],
|
||||
"detect_code": [
|
||||
"0781"
|
||||
],
|
||||
"components_add": [
|
||||
"SECUREF"
|
||||
]
|
||||
},
|
||||
"MCU_STM32L4R9xI": {
|
||||
|
|
Loading…
Reference in New Issue