mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat: add example to re-enable jtag using hmac peripheral
This commit is contained in:
parent
acb733845f
commit
37adea9a14
@ -232,6 +232,10 @@ JTAG with Flash Encryption or Secure Boot
|
||||
|
||||
By default, enabling Flash Encryption and/or Secure Boot will disable JTAG debugging. On first boot, the bootloader will burn an eFuse bit to permanently disable JTAG at the same time it enables the other features.
|
||||
|
||||
.. only:: SOC_HMAC_SUPPORTED
|
||||
|
||||
Please note that once JTAG is permanently disabled, it cannot be re-enabled for JTAG access. However, we do have the option of disabling JTAG softly. For more details on soft disabling and re-enabling soft-disabled JTAG, please refer to the :ref:`hmac_for_enabling_jtag`.
|
||||
|
||||
The project configuration option :ref:`CONFIG_SECURE_BOOT_ALLOW_JTAG` will keep JTAG enabled at this time, removing all physical security but allowing debugging. (Although the name suggests Secure Boot, this option can be applied even when only Flash Encryption is enabled).
|
||||
|
||||
However, OpenOCD may attempt to automatically read and write the flash in order to set :ref:`software breakpoints <jtag-debugging-tip-where-breakpoints>`. This has two problems:
|
||||
|
@ -132,6 +132,8 @@ JTAG enables
|
||||
2. Pass this key value when calling the :cpp:func:`esp_hmac_jtag_enable` function from the firmware.
|
||||
3. To re-disable JTAG in the firmware, reset the system or call :cpp:func:`esp_hmac_jtag_disable`.
|
||||
|
||||
End-to-end example of soft disable and re-enable JTAG workflow: :example:`security/hmac_soft_jtag`
|
||||
|
||||
For more details, see **{IDF_TARGET_NAME} Technical Reference Manual** > **HMAC Accelerator (HMAC)** [`PDF <{IDF_TARGET_TRM_EN_URL}#hmac>`__].
|
||||
|
||||
|
||||
|
@ -6,6 +6,17 @@ examples/security/flash_encryption:
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
|
||||
examples/security/hmac_soft_jtag:
|
||||
disable:
|
||||
- if: SOC_HMAC_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET not in ["esp32c6"]
|
||||
reason: sufficient to test on one HMAC-capable chip
|
||||
depends_components:
|
||||
- esp_hw_support
|
||||
depends_filepatterns:
|
||||
- examples/security/hmac_soft_jtag/**/*
|
||||
|
||||
examples/security/nvs_encryption_hmac:
|
||||
disable:
|
||||
- if: SOC_HMAC_SUPPORTED != 1
|
||||
|
8
examples/security/hmac_soft_jtag/CMakeLists.txt
Normal file
8
examples/security/hmac_soft_jtag/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
# For more information about build system see
|
||||
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(hmac_soft_jtag)
|
113
examples/security/hmac_soft_jtag/README.md
Normal file
113
examples/security/hmac_soft_jtag/README.md
Normal file
@ -0,0 +1,113 @@
|
||||
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# JTAG Re-enable Example
|
||||
|
||||
This example showcases the use of HMAC peripheral for enabling the soft-disabled JTAG interface.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
This example can be executed on any development board with a supported Espressif SOC chip - possessing a built-in HMAC peripheral (see `Supported Targets` table above).
|
||||
|
||||
### Configure the device
|
||||
|
||||
To configure the device for JTAG access, follow these steps:
|
||||
|
||||
**Note:** Before running the jtag_example_helper.py script, make sure to install the required dependencies by running the following command:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**Step 1:** Check JTAG status.
|
||||
|
||||
```bash
|
||||
python jtag_example_helper.py check_jtag_status
|
||||
```
|
||||
|
||||
If device is soft disabled, this example can re-enable it using further steps.
|
||||
|
||||
**Step 2:** Generate a 32 bytes HMAC key.
|
||||
|
||||
```bash
|
||||
python jtag_example_helper.py generate_hmac_key <KEY_FILE>.bin
|
||||
```
|
||||
|
||||
This generates a new 32-byte random HMAC key and store it in given file.
|
||||
|
||||
**Step 3:** Run the following command to burn the eFuse with the generated HMAC key with appropriate purpose. You can use purpose either HMAC_DOWN_ALL or HMAC_DOWN_JTAG. Check efuse summary to identify an available empty key block.
|
||||
|
||||
```bash
|
||||
espefuse.py -p $ESPPORT burn_key <KEY_BLOCK_NO> <KEY_FILE>.bin HMAC_DOWN_ALL
|
||||
```
|
||||
|
||||
**Step 4:** Generate token data from the HMAC key. Keep this token data handy before re-enabling JTAG access.
|
||||
|
||||
```bash
|
||||
python jtag_example_helper.py generate_token <KEY_FILE>.bin
|
||||
```
|
||||
|
||||
### Configure the project
|
||||
|
||||
Before the project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
|
||||
|
||||
Key block to be used for re-enabling JTAG can be configured in the project configuration menu, under ``Example Configuration`` > ``key block to be used``. The default value is -1, indicating that the example will use the first found keys with the purpose either HMAC_DOWN_ALL or HMAC_DOWN_JTAG.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run the monitor tool to view the serial output:
|
||||
|
||||
```bash
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
It will open console to enter command. Refer [Re-enable & Disable JTAG](#Re-enable-&-Disable-JTAG) to know more about usage of example.
|
||||
|
||||
(To exit the serial monitor, type `Ctrl-]`.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
### Re-enable & Disable JTAG
|
||||
|
||||
#### Re-enable JTAG
|
||||
|
||||
This re-enables JTAG access until the next reboot or until disabled using this example. For disabling JTAG, refer [Disable JTAG](#Disable-JTAG)
|
||||
|
||||
**Note:** Even upon successful return, JTAG will only be enabled with a valid token_data.
|
||||
|
||||
```bash
|
||||
enable_jtag <token_data>
|
||||
```
|
||||
|
||||
Console logs while re-enabling JTAG:
|
||||
|
||||
```bash
|
||||
I (314) main_task: Calling app_main()
|
||||
Type 'help' to get the list of commands.
|
||||
Use UP/DOWN arrows to navigate through command history.
|
||||
Press TAB when typing command name to auto-complete.
|
||||
I (394) main_task: Returned from app_main()
|
||||
esp32c6> enable_jtag b2a49b1cce1be922bb7e431277413e3e8e6c3e8e6e17625c50ac66a9a857949b
|
||||
I (10974) jtag_re_enable: Device is ready to re-enable.
|
||||
I (10974) jtag_re_enable: Using HMAC key at block 8 with purpose HMAC_DOWN_JTAG
|
||||
I (10984) jtag: JTAG re-enablement workflow performed, please check the JTAG connection manually
|
||||
esp32c6>
|
||||
```
|
||||
|
||||
#### Disable JTAG
|
||||
|
||||
This disables the temporarily enabled JTAG access.
|
||||
|
||||
```bash
|
||||
disable_jtag
|
||||
```
|
||||
|
||||
Console logs while disabling JTAG:
|
||||
|
||||
```bash
|
||||
esp32c6> disable_jtag
|
||||
I (25104) jtag_re_enable: JTAG disabled temporarily
|
||||
esp32c6>
|
||||
```
|
86
examples/security/hmac_soft_jtag/jtag_example_helper.py
Normal file
86
examples/security/hmac_soft_jtag/jtag_example_helper.py
Normal file
@ -0,0 +1,86 @@
|
||||
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
import argparse
|
||||
import binascii
|
||||
import hashlib
|
||||
import hmac
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
def generate_token_data(hmac_key_file: str) -> None:
|
||||
with open(hmac_key_file, 'rb') as file:
|
||||
key_data = file.read()
|
||||
data = bytes([0] * 32)
|
||||
token_data = hmac.HMAC(key_data, data, hashlib.sha256).digest()
|
||||
token_hex = binascii.hexlify(token_data).decode('utf-8')
|
||||
print(token_hex)
|
||||
|
||||
|
||||
def generate_hmac_key(hmac_key_file: str) -> None:
|
||||
hmac_key = os.urandom(32)
|
||||
with open(hmac_key_file, 'wb') as file:
|
||||
file.write(hmac_key)
|
||||
|
||||
|
||||
def check_jtag_status() -> None:
|
||||
esp_port = os.getenv('ESPPORT')
|
||||
if not esp_port:
|
||||
raise RuntimeError('ESPPORT not specified')
|
||||
|
||||
output = subprocess.check_output(['espefuse.py', 'summary']).decode('utf-8')
|
||||
|
||||
# check if JTAG is permenently/hard disabled
|
||||
if ('DIS_PAD_JTAG' in output and 'JTAG = True' in output) or ('HARD_DIS_JTAG' in output and 'JTAG = True' in output):
|
||||
print('JTAG functionality is permanently disabled')
|
||||
else:
|
||||
print('JTAG functionality is not permanently disabled')
|
||||
|
||||
# check if JTAG is software disabled
|
||||
soft_dis_value = None
|
||||
lines = output.split('\n')
|
||||
for line in lines:
|
||||
if 'SOFT_DIS_JTAG' in line:
|
||||
hex_value = line.split('=')[-1].split(' ')[1] # Extract the hexadecimal part
|
||||
soft_dis_value = int(hex_value, 16)
|
||||
break
|
||||
|
||||
if soft_dis_value is not None:
|
||||
# Count the number of 1's in the binary representation of soft_dis_value
|
||||
ones_count = bin(soft_dis_value).count('1')
|
||||
if ones_count % 2 != 0:
|
||||
print('JTAG is software disabled')
|
||||
else:
|
||||
print('JTAG is not software disabled')
|
||||
else:
|
||||
print('SOFT_DIS_JTAG value not found in the output')
|
||||
|
||||
print('If JTAG is permenently disabled, it cannot be re-enabled.\nThis example re-enables only software disabled JTAG access')
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers(dest='command')
|
||||
|
||||
subparsers.add_parser('check_jtag_status', help='Check JTAG current status')
|
||||
|
||||
hmac_generator_parser = subparsers.add_parser('generate_hmac_key')
|
||||
hmac_generator_parser.add_argument('hmac_key_file', help='File to store generated HMAC key')
|
||||
|
||||
token_generator_parser = subparsers.add_parser('generate_token')
|
||||
token_generator_parser.add_argument('hmac_key_file', help='File containing the HMAC key')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == 'check_jtag_status':
|
||||
check_jtag_status()
|
||||
elif args.command == 'generate_hmac_key':
|
||||
generate_hmac_key(args.hmac_key_file)
|
||||
elif args.command == 'generate_token':
|
||||
generate_token_data(args.hmac_key_file)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
2
examples/security/hmac_soft_jtag/main/CMakeLists.txt
Normal file
2
examples/security/hmac_soft_jtag/main/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
idf_component_register(SRCS "example_main.c" "jtag_commands.c"
|
||||
PRIV_INCLUDE_DIRS ".")
|
13
examples/security/hmac_soft_jtag/main/Kconfig.projbuild
Normal file
13
examples/security/hmac_soft_jtag/main/Kconfig.projbuild
Normal file
@ -0,0 +1,13 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_JTAG_SEC_HMAC_EFUSE_KEY_ID
|
||||
int "eFuse key ID storing the HMAC key"
|
||||
range -1 5
|
||||
default -1
|
||||
help
|
||||
The eFuse block key ID stores the HMAC key necessary for deriving token data to enable JTAG access.
|
||||
|
||||
Note: If set to -1, the system will attempt to use the first found keys with the purpose
|
||||
either HMAC_DOWN_ALL or HMAC_DOWN_JTAG.
|
||||
|
||||
endmenu
|
43
examples/security/hmac_soft_jtag/main/example_main.c
Normal file
43
examples/security/hmac_soft_jtag/main/example_main.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_console.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "jtag_commands.h"
|
||||
|
||||
#define PROMPT_STR CONFIG_IDF_TARGET
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
repl_config.prompt = PROMPT_STR ">";
|
||||
repl_config.max_cmdline_length = 256;
|
||||
|
||||
/* Register commands */
|
||||
esp_console_register_help_command();
|
||||
register_jtag_commands();
|
||||
|
||||
#if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) || defined(CONFIG_ESP_CONSOLE_UART_CUSTOM)
|
||||
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
|
||||
|
||||
#elif defined(CONFIG_ESP_CONSOLE_USB_CDC)
|
||||
esp_console_dev_usb_cdc_config_t hw_config = ESP_CONSOLE_DEV_CDC_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_usb_cdc(&hw_config, &repl_config, &repl));
|
||||
|
||||
#elif defined(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG)
|
||||
esp_console_dev_usb_serial_jtag_config_t hw_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&hw_config, &repl_config, &repl));
|
||||
|
||||
#else
|
||||
#error Unsupported console type
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
204
examples/security/hmac_soft_jtag/main/jtag_commands.c
Normal file
204
examples/security/hmac_soft_jtag/main/jtag_commands.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_hmac.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
|
||||
#define HMAC_KEY_SIZE 32
|
||||
#define TOKEN_DATA_SIZE 32
|
||||
|
||||
static const char* TAG = "jtag_re_enable";
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *token_data;
|
||||
struct arg_end *end;
|
||||
} command_args_t;
|
||||
|
||||
static command_args_t command_args;
|
||||
|
||||
static bool is_hexadecimal(const char *str)
|
||||
{
|
||||
if (str == NULL || *str == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (*str != '\0') {
|
||||
if (!isxdigit((unsigned char)*str)) {
|
||||
return false;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *esp_efuse_purpose_str(esp_efuse_purpose_t purpose)
|
||||
{
|
||||
switch (purpose) {
|
||||
case ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL:
|
||||
return "HMAC_DOWN_ALL";
|
||||
case ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG:
|
||||
return "HMAC_DOWN_JTAG";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t is_device_ready_to_re_enable(void)
|
||||
{
|
||||
bool flag_jtag_hard_dis;
|
||||
#if SOC_EFUSE_HARD_DIS_JTAG
|
||||
flag_jtag_hard_dis = esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
#else
|
||||
flag_jtag_hard_dis = esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
#endif
|
||||
|
||||
if (flag_jtag_hard_dis) {
|
||||
ESP_LOGE(TAG, "JTAG permenently disabled. Can't re-enable.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
size_t out_cnt = 0;
|
||||
if (ESP_OK != esp_efuse_read_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, &out_cnt)) {
|
||||
ESP_LOGE(TAG, "Error obtaining value for SOFT_DIS_JTAG");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (out_cnt == 0) {
|
||||
ESP_LOGI(TAG, "JTAG soft disable efuse bit is not programmed, hence JTAG is already enabled");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t re_enable_jtag_utility(uint8_t token_data[])
|
||||
{
|
||||
esp_err_t status;
|
||||
|
||||
// Read the configured key block number from Kconfig
|
||||
int configured_block_number = CONFIG_EXAMPLE_JTAG_SEC_HMAC_EFUSE_KEY_ID;
|
||||
|
||||
if (configured_block_number != -1) {
|
||||
// User has configured a specific key block number
|
||||
ESP_LOGI(TAG, "Using user-configured key block number %d for authentication", configured_block_number);
|
||||
status = esp_hmac_jtag_enable(configured_block_number, token_data);
|
||||
} else {
|
||||
esp_efuse_purpose_t purposes[] = {
|
||||
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL,
|
||||
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG
|
||||
};
|
||||
|
||||
// Check if there is already a key block with the desired purpose
|
||||
esp_efuse_block_t block;
|
||||
status = ESP_FAIL;
|
||||
for (unsigned i = 0; i < sizeof(purposes) / sizeof(esp_efuse_purpose_t); i++) {
|
||||
if (esp_efuse_find_purpose(purposes[i], &block)) {
|
||||
// key block with appropriate purpose found
|
||||
ESP_LOGI(TAG, "Using HMAC key at block %d with purpose %s for authentication", block - (int)EFUSE_BLK4, esp_efuse_purpose_str(purposes[i]));
|
||||
status = status && esp_hmac_jtag_enable(block - (int)EFUSE_BLK4, token_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (EFUSE_BLK_KEY_MAX == block) {
|
||||
ESP_LOGI(TAG, "HMAC key is not burned with required purpose. Please refer to device configuration in example readme for more details.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ESP_OK != status) {
|
||||
ESP_LOGI(TAG, "Error in re-enabling JTAG");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t re_enable_jtag(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **) &command_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, command_args.end, argv[0]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (ESP_OK != is_device_ready_to_re_enable()) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "Device is ready to re-enable.");
|
||||
|
||||
const char* arg_token_data_str = command_args.token_data->sval[0];
|
||||
if (strlen(arg_token_data_str) != TOKEN_DATA_SIZE * 2 || !is_hexadecimal(arg_token_data_str)) {
|
||||
ESP_LOGE(TAG, "Invalid token_data. The token data should be 64 hexadecimal characters.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Convert the string to uint8_t array
|
||||
uint8_t token_data[TOKEN_DATA_SIZE];
|
||||
for (int i = 0; i < TOKEN_DATA_SIZE; ++i) {
|
||||
sscanf(arg_token_data_str + 2 * i, "%2hhx", &token_data[i]);
|
||||
}
|
||||
|
||||
if (ESP_OK != re_enable_jtag_utility(token_data)) {
|
||||
ESP_LOGI(TAG, "JTAG re-enabling failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI("jtag", "JTAG re-enablement workflow performed, please check the JTAG connection manually");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void register_enable_jtag(void)
|
||||
{
|
||||
command_args.token_data = arg_str1(NULL, NULL, "<token_data>", "token_data");
|
||||
command_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "enable_jtag",
|
||||
.help = "Re-enables software JTAG access.\n\t Usage: enable_jtag <token_data>",
|
||||
.hint = NULL,
|
||||
.func = &re_enable_jtag,
|
||||
.argtable = &command_args,
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
static esp_err_t disable_jtag(int argc, char **argv)
|
||||
{
|
||||
if (ESP_OK != esp_hmac_jtag_disable()) {
|
||||
ESP_LOGE(TAG, "Failed to disable JTAG");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "JTAG disabled temporarily");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void register_disable_jtag(void)
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "disable_jtag",
|
||||
.help = "Disables software JTAG access",
|
||||
.hint = NULL,
|
||||
.func = &disable_jtag,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
void register_jtag_commands(void)
|
||||
{
|
||||
register_enable_jtag();
|
||||
register_disable_jtag();
|
||||
}
|
8
examples/security/hmac_soft_jtag/main/jtag_commands.h
Normal file
8
examples/security/hmac_soft_jtag/main/jtag_commands.h
Normal file
@ -0,0 +1,8 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
void register_jtag_commands(void);
|
51
examples/security/hmac_soft_jtag/pytest_jtag_example.py
Normal file
51
examples/security/hmac_soft_jtag/pytest_jtag_example.py
Normal file
@ -0,0 +1,51 @@
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# # SPDX-License-Identifier: CC0-1.0
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
|
||||
import pexpect
|
||||
import pytest
|
||||
from pytest_embedded_idf import IdfDut
|
||||
|
||||
|
||||
def run_gdb_test(dut: IdfDut) -> None:
|
||||
with open(os.path.join(dut.logdir, 'ocd.txt'), 'w') as ocd_log, \
|
||||
pexpect.spawn(f'openocd -f board/esp32c6-builtin.cfg',
|
||||
timeout=60,
|
||||
logfile=ocd_log,
|
||||
encoding='utf-8',
|
||||
codec_errors='ignore') as p:
|
||||
try:
|
||||
p.expect(re.compile(r'JTAG tap: esp32c6.cpu tap/device found'), timeout=5)
|
||||
logging.info('JTAG is enabled.')
|
||||
|
||||
except pexpect.TIMEOUT:
|
||||
logging.info('JTAG is disabled')
|
||||
|
||||
finally:
|
||||
p.terminate()
|
||||
p.kill(signal.SIGKILL)
|
||||
|
||||
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.jtag_re_enable
|
||||
def test_jtag_re_enable(dut: IdfDut) -> None:
|
||||
|
||||
dut.expect_exact('esp32c6>', timeout=30)
|
||||
|
||||
logging.info('Initially:')
|
||||
run_gdb_test(dut)
|
||||
|
||||
logging.info('After calling enable_jtag:')
|
||||
# The following token data is generated using the HMAC key:
|
||||
# {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
|
||||
dut.write('enable_jtag b2a49b1cce1be922bb7e431277413e3e8e6c3e8e6e17625c50ac66a9a857949b')
|
||||
dut.expect('JTAG re-enablement workflow performed', timeout=30)
|
||||
run_gdb_test(dut)
|
||||
|
||||
logging.info('After calling disable_jtag:')
|
||||
dut.write('disable_jtag')
|
||||
dut.expect('JTAG disabled temporarily', timeout=30)
|
||||
run_gdb_test(dut)
|
1
examples/security/hmac_soft_jtag/requirements.txt
Normal file
1
examples/security/hmac_soft_jtag/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
esptool
|
0
examples/security/hmac_soft_jtag/sdkconfig.defaults
Normal file
0
examples/security/hmac_soft_jtag/sdkconfig.defaults
Normal file
@ -0,0 +1,3 @@
|
||||
# Changing channel for console output
|
||||
#
|
||||
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
|
@ -103,6 +103,7 @@ ENV_MARKERS = {
|
||||
'i2c_oled': 'Runner with ssd1306 I2C oled connected',
|
||||
'httpbin': 'runner for tests that need to access the httpbin service',
|
||||
'flash_4mb': 'C2 runners with 4 MB flash',
|
||||
'jtag_re_enable': 'Runner to re-enable jtag which is softly disabled by burning bit SOFT_DIS_JTAG on eFuse',
|
||||
# multi-dut markers
|
||||
'multi_dut_modbus_rs485': 'a pair of runners connected by RS485 bus',
|
||||
'ieee802154': 'ieee802154 related tests should run on ieee802154 runners.',
|
||||
|
Loading…
Reference in New Issue
Block a user