Skip to content

Commit

Permalink
feat(espefuse): Support XTS_AES_256_KEY key_purpose for ESP32P4
Browse files Browse the repository at this point in the history
  • Loading branch information
KonstantinKondrashov authored and peterdragun committed Jul 16, 2024
1 parent 005c3e3 commit fcf2277
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
1 change: 1 addition & 0 deletions espefuse/efuse/esp32p4/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ class EfuseKeyPurposeField(EfuseField):
("SECURE_BOOT_DIGEST1", 10, "DIGEST", None, "no_need_rd_protect"), # SECURE_BOOT_DIGEST1 (Secure Boot key digest)
("SECURE_BOOT_DIGEST2", 11, "DIGEST", None, "no_need_rd_protect"), # SECURE_BOOT_DIGEST2 (Secure Boot key digest)
("KM_INIT_KEY", 12, None, None, "need_rd_protect"), # init key that is used for the generation of AES/ECDSA key
("XTS_AES_256_KEY", -1, "VIRTUAL", None, "no_need_rd_protect"), # Virtual purpose splits to XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2
]
# fmt: on
KEY_PURPOSES_NAME = [name[0] for name in KEY_PURPOSES]
Expand Down
67 changes: 67 additions & 0 deletions espefuse/efuse/esp32p4/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later

import argparse
import io
import os # noqa: F401. It is used in IDF scripts
import traceback

Expand Down Expand Up @@ -191,6 +192,67 @@ def adc_info(esp, efuses, args):
print("not supported yet")


def key_block_is_unused(block, key_purpose_block):
if not block.is_readable() or not block.is_writeable():
return False

if key_purpose_block.get() != "USER" or not key_purpose_block.is_writeable():
return False

if not block.get_bitstring().all(False):
return False

return True


def get_next_key_block(efuses, current_key_block, block_name_list):
key_blocks = [b for b in efuses.blocks if b.key_purpose_name]
start = key_blocks.index(current_key_block)

# Sort key blocks so that we pick the next free block (and loop around if necessary)
key_blocks = key_blocks[start:] + key_blocks[0:start]

# Exclude any other blocks that will be be burned
key_blocks = [b for b in key_blocks if b.name not in block_name_list]

for block in key_blocks:
key_purpose_block = efuses[block.key_purpose_name]
if key_block_is_unused(block, key_purpose_block):
return block

return None


def split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list):
i = keypurpose_list.index("XTS_AES_256_KEY")
block_name = block_name_list[i]

block_num = efuses.get_index_block_by_name(block_name)
block = efuses.blocks[block_num]

data = datafile_list[i].read()
if len(data) != 64:
raise esptool.FatalError(
"Incorrect key file size %d, XTS_AES_256_KEY should be 64 bytes" % len(data)
)

key_block_2 = get_next_key_block(efuses, block, block_name_list)
if not key_block_2:
raise esptool.FatalError("XTS_AES_256_KEY requires two free keyblocks")

keypurpose_list.append("XTS_AES_256_KEY_1")
datafile_list.append(io.BytesIO(data[:32]))
block_name_list.append(block_name)

keypurpose_list.append("XTS_AES_256_KEY_2")
datafile_list.append(io.BytesIO(data[32:]))
block_name_list.append(key_block_2.name)

keypurpose_list.pop(i)
datafile_list.pop(i)
block_name_list.pop(i)


def burn_key(esp, efuses, args, digest=None):
if digest is None:
datafile_list = args.keyfile[
Expand All @@ -206,6 +268,11 @@ def burn_key(esp, efuses, args, digest=None):
0 : len([name for name in args.keypurpose if name is not None]) :
]

if "XTS_AES_256_KEY" in keypurpose_list:
# XTS_AES_256_KEY is not an actual HW key purpose, needs to be split into
# XTS_AES_256_KEY_1 and XTS_AES_256_KEY_2
split_512_bit_key(efuses, block_name_list, datafile_list, keypurpose_list)

util.check_duplicate_name_in_list(block_name_list)
if len(block_name_list) != len(datafile_list) or len(block_name_list) != len(
keypurpose_list
Expand Down
12 changes: 6 additions & 6 deletions test/test_espefuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -962,8 +962,8 @@ def test_burn_key_with_34_coding_scheme(self):
self.check_data_block_in_log(output, f"{IMAGES_DIR}/192bit_2")

@pytest.mark.skipif(
arg_chip not in ["esp32s2", "esp32s3"],
reason="512 bit keys are only supported on ESP32-S2 and S3",
arg_chip not in ["esp32s2", "esp32s3", "esp32p4"],
reason="512 bit keys are only supported on ESP32-S2, S3, and P4",
)
def test_burn_key_512bit(self):
self.espefuse_py(
Expand All @@ -980,8 +980,8 @@ def test_burn_key_512bit(self):
)

@pytest.mark.skipif(
arg_chip not in ["esp32s2", "esp32s3"],
reason="512 bit keys are only supported on ESP32-S2 and S3",
arg_chip not in ["esp32s2", "esp32s3", "esp32p4"],
reason="512 bit keys are only supported on ESP32-S2, S3, and P4",
)
def test_burn_key_512bit_non_consecutive_blocks(self):
# Burn efuses seperately to test different kinds
Expand Down Expand Up @@ -1023,8 +1023,8 @@ def test_burn_key_512bit_non_consecutive_blocks(self):
) in output

@pytest.mark.skipif(
arg_chip not in ["esp32s2", "esp32s3"],
reason="512 bit keys are only supported on ESP32-S2 and S3",
arg_chip not in ["esp32s2", "esp32s3", "esp32p4"],
reason="512 bit keys are only supported on ESP32-S2, S3, and P4",
)
def test_burn_key_512bit_non_consecutive_blocks_loop_around(self):
self.espefuse_py(
Expand Down

0 comments on commit fcf2277

Please sign in to comment.