#include "fcntl.h"
#include "unistd.h"
#include "stdio.h"
+#include "platform_core.h"
#if defined(BUILD_APPLICATION_STANDARD) && !defined(BUILD_RECOVERY_IMAGE)
#include "diag_filter.h"
#endif
printf("0x570007a0 %x \r\n", readw(B_MAINTENANCE_3));
printf("0x570007a8 =%x,0x570007ac =%x \r\n", readw(0x570007a8), readw(0x570007ac));
#endif
+}
+
+__attribute__((noinline)) void test_msdio(void)
+{
+ uint16_t value = readw(SPI_HOST_REG_FOR_HADR_DOG_TEST); // SDIO HOST地址,访问会造成硬件狗超时
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 1);
+}
+
+// 5702c014这个寄存器是不掉电的寄存器,当芯片复位这个寄存器的值还会在的,所以用来记录程序跑到了哪里
+// 通过访问各个总线下面的寄存器来判断总线时钟是否正常,然后用5702c014记录时钟访问情况,然后在芯片复位后在ssb里面打印这个值
+__attribute__((noinline)) void test_uart_h0(void)
+{
+ uint16_t value = readw(UART1_BASE + 0x24); // uart h0 的整数分频系数配置寄存器
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 2);
+}
+
+__attribute__((noinline)) void test_timer0(void)
+{
+ uint16_t value = readw(TIMER_0_BASE_ADDR); //timer0的计数值的初始值
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 3);
+}
+
+__attribute__((noinline)) void test_mdma(void)
+{
+ uint16_t value = readw(DMA_BASE_ADDR); // mdma的通道0的源地址寄存器
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 4);
+}
+
+__attribute__((noinline)) void test_i2c(void)
+{
+ uint16_t value = readw(I2C_BUS_0_BASE_ADDR); // i2c0的控制寄存器,可以将基地址配置实际使用IP的基地址
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 5);
+}
+
+__attribute__((noinline)) void test_qspi(void)
+{
+ uint16_t value = readw(SPI_BUS_5_BASE_ADDR); // qspi2的控制寄存器
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 6);
+}
+
+
+__attribute__((noinline)) void test_spi0(void)
+{
+ uint16_t value = readw(SPI_BUS_0_BASE_ADDR); // spi0的控制寄存器,可以将基地址配置实际使用IP的基地址
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 7);
+}
+
+__attribute__((noinline)) void test_nandflash(void)
+{
+ uint16_t value = readw(NAND_QSPI_BASE_ADDR); // qspi to nand的控制寄存器
+ writew(BUS_TEST_REG, value);
+ writew(BUS_TEST_REG, 8);
+}
+
+__attribute__((noinline)) void test_main_ahb_bus(void)
+{
+#if defined(BUILD_APPLICATION_STANDARD)
+ test_uart_h0();
+ test_timer0();
+ test_mdma();
+ // test_i2c(); 使用时候需要先开启时钟,时钟在clocks_config_pri.c里面配置
+ // test_qspi(); 使用时候需要先开启时钟,时钟在clocks_config_pri.c里面配置
+ // test_spi0(); 使用时候需要先开启时钟,时钟在clocks_config_pri.c里面配置
+ test_nandflash();
+#endif
+}
+
+void test_mcu_bus(void)
+{
+ test_main_ahb_bus();
}
\ No newline at end of file
* Description: NV - key_id.
*/
- #ifndef __KEY_ID_H__
- #define __KEY_ID_H__
-
- #define REGION_KEY_NUMS 0x1000 /* 每个区域容纳key_id的个数 */
-
-
- /* Please use the format of NV_ID_XXX */
-
- /* system factory key_id [0x0001,0x1000) */
-
-
- /* user factory key_id [0x1000,0x2000) */
+#ifndef __KEY_ID_H__
+#define __KEY_ID_H__
+
+#define REGION_KEY_NUMS 0x1000 /* 每个区域容纳key_id的个数 */
+
+
+/* Please use the format of NV_ID_XXX */
+
+/* system factory key_id [0x0001,0x1000) */
+
+
+/* user factory key_id [0x1000,0x2000) */
#define NV_ID_CUSTOM_KEY_SERIAL_NUM 0x1010 /* 序列号 */
-
- /* system normal key_id [0x2000,0x3000) */
- #define NV_ID_SECURE_CONN 0x2001 /* secure connect */
- #define NV_ID_OFFLINELOG_ENBALE_FLAG 0x2002 /* Offline log enable flag */
-
- #define NV_ID_BTSRV_LOCAL_DEV_INFO 0x2101 /* btsrv_local_device_info_t */
- #define NV_ID_BTSRV_PAIRED_DEV_INFO 0x2102 /* btsrv_paired_device_info_t */
-
- #define NV_ID_BTSRV_CALIBRATION_CONFIG 0x2103 /* btsrv_local_tx_power_info_t */
- #define BTH_NV_SEC_ID 0x2104 /* bth_product_data_config_t */
- /* user normal key_id [0x3000,0x4000) */
- #define NV_ID_AUDIO_VQE_PARAM 0x320C /* 3A params for VOIP scene, audio_vqe_param_t */
- #define NV_ID_AUDIO_VQE_KWS_PARAM 0x320D /* 3A params for KWS scene, audio_vqe_param_t */
-
- /* reserved key_id [0x4000,0xFFFF) */
- #define NV_ID_SAMPLE_0 0x4000 /* Eg. */
- #define NV_ID_SAMPLE_1 0x4001 /* Eg. */
- #define NV_ID_SAMPLE_2 0x4002 /* Eg. */
- #define NV_ID_SAMPLE_3 0x4003 /* Eg. */
- #define NV_ID_SAMPLE_4 0x4004 /* Eg. */
- #define NV_ID_FTM_CONFIG 0x4109
- #define NV_ID_RESTORE_ENABLE 0xA000 /* NV restore factory region flag */
-
-
- #endif /* __KEY_ID_H__ */
+
+/* system normal key_id [0x2000,0x3000) */
+#define NV_ID_SECURE_CONN 0x2001 /* secure connect */
+#define NV_ID_OFFLINELOG_ENBALE_FLAG 0x2002 /* Offline log enable flag */
+
+#define NV_ID_BTSRV_LOCAL_DEV_INFO 0x2101 /* btsrv_local_device_info_t */
+#define NV_ID_BTSRV_PAIRED_DEV_INFO 0x2102 /* btsrv_paired_device_info_t */
+
+#define NV_ID_BTSRV_CALIBRATION_CONFIG 0x2103 /* btsrv_local_tx_power_info_t */
+#define BTH_NV_SEC_ID 0x2104 /* bth_product_data_config_t */
+
+#define NV_ID_SYS_LANGUAGE_ID 0x2105 /* sys_language_id */
+#define NV_ID_SYS_PRODUCT_INFO 0x2106 /* sys_product_info */
+
+/* dial market key_id [0x2500,0x2600) */
+#define NV_ID_SECURE_DIAL 0x2500 /* secure dial */
+
+/* user normal key_id [0x3000,0x4000) */
+#define NV_ID_AUDIO_VQE_PARAM 0x320C /* 3A params for VOIP scene, audio_vqe_param_t */
+#define NV_ID_AUDIO_VQE_KWS_PARAM 0x320D /* 3A params for KWS scene, audio_vqe_param_t */
+
+/* reserved key_id [0x4000,0xFFFF) */
+#define NV_ID_SAMPLE_0 0x4000 /* Eg. */
+#define NV_ID_SAMPLE_1 0x4001 /* Eg. */
+#define NV_ID_SAMPLE_2 0x4002 /* Eg. */
+#define NV_ID_SAMPLE_3 0x4003 /* Eg. */
+#define NV_ID_SAMPLE_4 0x4004 /* Eg. */
+#define NV_ID_FTM_CONFIG 0x4109
+#define NV_ID_RESTORE_ENABLE 0xA000 /* NV restore factory region flag */
+
+
+#endif /* __KEY_ID_H__ */
\ No newline at end of file
--- /dev/null
+/**
+ * Copyright (c) @CompanyNameMagicTag 2023-2023. All rights reserved.
+ *
+ * Description: NV crypto
+ * Author: @CompanyNameTag
+ * History:
+ * 2023-04-27, Create file.
+ */
+
+#include "nv_porting.h"
+
+#if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES)
+#include "cipher.h"
+#include "cipher_aead.h"
+#include "common_def.h"
+#include "efuse.h"
+#include "trng.h"
+#include "cipher_api.h"
+
+#define INVALID_HANDLE (0xFFFFFFFF)
+#define NV_HEADER_LENGTH 16
+#define NV_KEY_LENGTH 16
+#define NV_IV_LENGTH 12
+#define NV_TAG_LENGTH 16
+#define NV_DIE_ID_LENGTH_BYTES 16
+#define NV_DIE_ID_LEN_WORDS 4
+#define NV_DIE_ID_HIGH_32 3
+#define NV_DIE_ID_LOW_32 0
+#define MATERIAL_LEN 16
+#define SALT_LEN 32
+#define PASSWORD_LEN 16
+#define OTP_RANDOM_POS 70
+#define DIE_ID_POS 0
+
+STATIC uint8_t ta_uuid[] = {0xCA, 0x2B, 0xF7, 0x6A, 0xFF, 0x79, 0x4E, 0xAC,
+ 0xA6, 0x3D, 0x4E, 0x0A, 0xAA, 0xEE, 0x6C, 0x77};
+
+typedef struct {
+ uint16_t enc_key;
+ uint16_t version;
+ uint32_t rnd;
+ uint32_t die_id;
+} kv_crypto_iv_info_t;
+
+typedef struct {
+ uint8_t type;
+ uint8_t upgrade;
+ uint16_t key_id;
+ uint16_t enc_key;
+ uint16_t version;
+ uint32_t rnd;
+ uint32_t die_id;
+} kv_crypto_key_info_t;
+
+static errcode_t make_section_key(uint8_t *section_key,
+ const kv_key_header_t *header,
+ uint32_t die_id_high32)
+{
+ kv_crypto_key_info_t *kv_crypto_key_info =
+ (kv_crypto_key_info_t *)(uintptr_t)section_key;
+ kv_crypto_key_info->type = header->type;
+ kv_crypto_key_info->upgrade = header->upgrade;
+ kv_crypto_key_info->key_id = header->key_id;
+ kv_crypto_key_info->enc_key = header->enc_key;
+ kv_crypto_key_info->version = header->version;
+ kv_crypto_key_info->rnd = header->rnd;
+ kv_crypto_key_info->die_id = die_id_high32;
+
+ return ERRCODE_SUCC;
+}
+
+static errcode_t make_iv(uint8_t *iv, const kv_key_header_t *header,
+ uint32_t die_id_low32)
+{
+ kv_crypto_iv_info_t *kv_crypto_iv_info =
+ (kv_crypto_iv_info_t *)(uintptr_t)iv;
+ kv_crypto_iv_info->enc_key = header->enc_key;
+ kv_crypto_iv_info->version = header->version;
+ kv_crypto_iv_info->rnd = header->rnd;
+ kv_crypto_iv_info->die_id = die_id_low32;
+ return ERRCODE_SUCC;
+}
+
+// Random OTP(16bytes)
+static errcode_t get_material1(uint8_t *material1, uint16_t material1_len)
+{
+ errcode_t ret = ERRCODE_FAIL;
+
+ ret = uapi_efuse_read_buffer(material1, OTP_RANDOM_POS, material1_len);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] uapi_efuse_read_buffer failed!! ret = 0x%x\r\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+// salt component: sectionkey || ta_uuid;
+// sectionkey component: type || owner || key_id || enc_key || version || rnd ||
+// DIE_ID
+static errcode_t get_salt(uint8_t *salt, uint32_t salt_len, uint32_t *die_id,
+ const kv_key_header_t *header)
+{
+ errcode_t ret = ERRCODE_FAIL;
+ uint8_t section_key[NV_KEY_LENGTH] = {0};
+
+ ret = make_section_key(section_key, header, die_id[NV_DIE_ID_HIGH_32]);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] make_section_key failed! ret = 0x%x\r\n", ret);
+ goto err_exit;
+ }
+ if (memcpy_s(salt, salt_len, section_key, NV_KEY_LENGTH) != EOK) {
+ nv_log_err("[NV] memcpy_s failed!\r\n");
+ goto err_exit;
+ }
+ if (memcpy_s(salt + NV_KEY_LENGTH, salt_len - NV_KEY_LENGTH, ta_uuid, sizeof(ta_uuid)) != EOK) {
+ nv_log_err("[NV] memcpy_s failed!\r\n");
+ goto err_exit;
+ }
+
+err_exit:
+ (void)memset_s(section_key, sizeof(section_key), 0, sizeof(section_key));
+ return ret;
+}
+
+// Using material1(16bytes) and salt(16bytes) to derive rootkey by HKDF
+static errcode_t get_password(uint8_t *password, uint32_t password_len,
+ const kv_key_header_t *header, uint32_t *die_id)
+{
+ uint8_t salt[SALT_LEN] = {0};
+ uint8_t material1[MATERIAL_LEN] = {0};
+ errcode_t ret = ERRCODE_FAIL;
+ uapi_drv_cipher_hkdf_t hkdf_param = {0};
+
+ ret = get_salt(salt, SALT_LEN, die_id, header);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] get salt failed!\r\n");
+ goto err_exit;
+ }
+
+ ret = get_material1(material1, MATERIAL_LEN);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] get material1 failed!\r\n");
+ goto err_exit;
+ }
+
+ hkdf_param.hmac_type = UAPI_DRV_CIPHER_HASH_TYPE_HMAC_SHA256;
+ hkdf_param.ikm = material1;
+ hkdf_param.ikm_length = MATERIAL_LEN;
+ hkdf_param.info = NULL;
+ hkdf_param.info_length = 0;
+ hkdf_param.salt = salt;
+ hkdf_param.salt_length = SALT_LEN;
+
+ ret = uapi_drv_cipher_hkdf(&hkdf_param, password, password_len);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] uapi_drv_cipher_hkdf failed!\r\n");
+ goto err_exit;
+ }
+
+ ret = ERRCODE_SUCC;
+err_exit:
+ (void)memset_s(salt, sizeof(salt), 0, sizeof(salt));
+ (void)memset_s(material1, sizeof(material1), 0, sizeof(material1));
+ return ret;
+}
+
+/* 创建加解密通道 */
+errcode_t nv_crypto_claim_aes(uint32_t *crypto_handle,
+ const kv_key_header_t *header)
+{
+ uint32_t cipher = INVALID_HANDLE;
+ uint32_t die_id[NV_DIE_ID_LEN_WORDS] = {0};
+ uint8_t password[PASSWORD_LEN] = {0};
+ uint8_t iv[NV_IV_LENGTH] = {0};
+ errcode_t ret;
+
+ /* 获取Die_id */
+ ret = uapi_efuse_get_die_id((uint8_t *)die_id, NV_DIE_ID_LENGTH_BYTES);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] get_die_id failed!\r\n");
+ goto err_exit;
+ }
+
+ /* 获取密钥 */
+ ret = get_password(password, PASSWORD_LEN, header, die_id);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] get_password failed!\r\n");
+ goto err_exit;
+ }
+
+ /* 获取iv */
+ ret = make_iv(iv, header, die_id[NV_DIE_ID_LOW_32]);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] make_iv failed!\r\n");
+ goto err_exit;
+ }
+
+ ret =
+ uapi_drv_cipher_symc_gcm_create(&cipher, password, PASSWORD_LEN, 0, iv,
+ sizeof(iv), NULL, 0, NV_TAG_LENGTH);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] uapi_drv_cipher_symc_gcm_create failed!\r\n");
+ goto err_exit;
+ }
+
+ *crypto_handle = cipher;
+err_exit:
+ (void)memset_s(password, sizeof(password), 0, sizeof(password));
+ (void)memset_s(die_id, sizeof(die_id), 0, sizeof(die_id));
+ (void)memset_s(iv, sizeof(iv), 0, sizeof(iv));
+ return ret;
+}
+
+/* 释放加解密通道 */
+void nv_crypto_release_aes(uint32_t crypto_handle)
+{
+ if (crypto_handle != INVALID_HANDLE) {
+ uapi_drv_cipher_symc_gcm_destroy(crypto_handle);
+ }
+}
+
+/* NV数据加密 */
+errcode_t nv_crypto_encode(uint32_t crypto_handle, const uintptr_t src,
+ uintptr_t dest, uint32_t length)
+{
+ errcode_t ret;
+ ret = uapi_drv_cipher_symc_gcm_encrypt_update(crypto_handle, (uint8_t *)src,
+ (uint8_t *)dest, length);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] encrypt failed!\r\n");
+ return ret;
+ }
+ return ret;
+}
+
+/* NV数据解密 */
+errcode_t nv_crypto_decode(uint32_t crypto_handle, const uintptr_t src,
+ uintptr_t dest, uint32_t length)
+{
+ errcode_t ret;
+ ret = uapi_drv_cipher_symc_gcm_decrypt_update(crypto_handle, (uint8_t *)src,
+ (uint8_t *)dest, length);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] decrypt failed!\r\n");
+ return ret;
+ }
+ return ret;
+}
+
+/* 获取加密Tag */
+errcode_t nv_crypto_get_tag(uint32_t crypto_handle, uint8_t *tag,
+ uint32_t *tag_len)
+{
+ errcode_t ret;
+ if (*tag_len < NV_TAG_LENGTH) {
+ return ERRCODE_NV_INVALID_PARAMS;
+ }
+
+ /* get tag */
+ ret = uapi_drv_cipher_symc_gcm_encrypt_get_tag(crypto_handle, tag,
+ NV_TAG_LENGTH);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] get tag failed!\r\n");
+ return ret;
+ }
+
+ *tag_len = NV_TAG_LENGTH;
+ return ERRCODE_SUCC;
+}
+
+/* 设置当前NV的Tag */
+errcode_t nv_crypto_set_tag(uint32_t crypto_handle, uint8_t *tag,
+ uint32_t tag_len)
+{
+ errcode_t ret;
+
+ ret = uapi_drv_cipher_symc_gcm_decrypt_set_tag(crypto_handle, tag, tag_len);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] set tag failed!\r\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+/* 校验Tag */
+errcode_t nv_crypto_validate_tag(uint32_t crypto_handle)
+{
+ errcode_t ret;
+
+ ret = uapi_drv_cipher_symc_gcm_decrypt_verify_tag(crypto_handle);
+ if (ret != ERRCODE_SUCC) {
+ nv_log_err("[NV] verify tag failed!\r\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+/* 获取随机数 */
+void nv_crypto_generate_random(uint32_t *rnd)
+{
+ (void)uapi_drv_cipher_trng_get_random(rnd);
+}
+
+/* 以下函数预留,可不实现 */
+errcode_t nv_crypto_start_hash(void)
+{
+ return ERRCODE_SUCC;
+}
+
+errcode_t nv_crypto_update_hash(const uint8_t *src, uint32_t length)
+{
+ unused(src);
+ unused(length);
+ return ERRCODE_SUCC;
+}
+
+errcode_t nv_crypto_complete_hash(uint8_t *hash)
+{
+ unused(hash);
+ return ERRCODE_SUCC;
+}
+
+#endif /* #if (CONFIG_NV_SUPPORT_ENCRYPT == NV_YES) */