feat(esptool): Print key_purpose name for get_security_info cmd

This commit is contained in:
Konstantin Kondrashov
2024-05-16 09:50:55 +03:00
parent 6bb2b922dd
commit ccd8c720e0
14 changed files with 218 additions and 21 deletions

View File

@@ -1284,7 +1284,16 @@ def get_security_info(esp, args):
print(title) print(title)
print("=" * len(title)) print("=" * len(title))
print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"]))) print("Flags: {:#010x} ({})".format(si["flags"], bin(si["flags"])))
print("Key Purposes: {}".format(si["key_purposes"])) if esp.KEY_PURPOSES:
print(f"Key Purposes: {si['key_purposes']}")
desc = "\n ".join(
[
f"BLOCK_KEY{key_num} - {esp.KEY_PURPOSES.get(purpose, 'UNKNOWN')}"
for key_num, purpose in enumerate(si["key_purposes"])
if key_num <= esp.EFUSE_MAX_KEY
]
)
print(f" {desc}")
if si["chip_id"] is not None and si["api_version"] is not None: if si["chip_id"] is not None and si["api_version"] is not None:
print("Chip ID: {}".format(si["chip_id"])) print("Chip ID: {}".format(si["chip_id"]))
print("API Version: {}".format(si["api_version"])) print("API Version: {}".format(si["api_version"]))

View File

@@ -5,7 +5,7 @@
import struct import struct
import time import time
from typing import Optional from typing import Dict, Optional
from ..loader import ESPLoader from ..loader import ESPLoader
from ..util import FatalError, NotSupportedError from ..util import FatalError, NotSupportedError
@@ -125,6 +125,8 @@ class ESP32ROM(ESPLoader):
UF2_FAMILY_ID = 0x1C5F21B0 UF2_FAMILY_ID = 0x1C5F21B0
KEY_PURPOSES: Dict[int, str] = {}
""" Try to read the BLOCK1 (encryption key) and check if it is valid """ """ Try to read the BLOCK1 (encryption key) and check if it is valid """
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):

View File

@@ -5,6 +5,7 @@
import struct import struct
import time import time
from typing import Dict
from .esp32c3 import ESP32C3ROM from .esp32c3 import ESP32C3ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -64,6 +65,8 @@ class ESP32C2ROM(ESP32C3ROM):
UF2_FAMILY_ID = 0x2B88D29C UF2_FAMILY_ID = 0x2B88D29C
KEY_PURPOSES: Dict[int, str] = {}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 1 num_word = 1
return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 22) & 0x07 return (self.read_reg(self.EFUSE_BLOCK2_ADDR + (4 * num_word)) >> 22) & 0x07

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
import struct import struct
from typing import Dict
from .esp32 import ESP32ROM from .esp32 import ESP32ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -99,6 +100,20 @@ class ESP32C3ROM(ESP32ROM):
UF2_FAMILY_ID = 0xD42BA06C UF2_FAMILY_ID = 0xD42BA06C
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "RESERVED",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 3 num_word = 3
return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07
@@ -179,8 +194,10 @@ class ESP32C3ROM(ESP32ROM):
) )
def get_key_block_purpose(self, key_block): def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5: if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError("Valid key block numbers must be in range 0-5") raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, shift = [ reg, shift = [
(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT),
@@ -194,7 +211,9 @@ class ESP32C3ROM(ESP32ROM):
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):
# Need to see an AES-128 key # Need to see an AES-128 key
purposes = [self.get_key_block_purpose(b) for b in range(6)] purposes = [
self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1)
]
return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes) return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes)

View File

@@ -4,6 +4,7 @@
import struct import struct
import time import time
from typing import Dict
from .esp32c6 import ESP32C6ROM from .esp32c6 import ESP32C6ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -52,6 +53,23 @@ class ESP32C5ROM(ESP32C6ROM):
UF2_FAMILY_ID = 0xF71C0343 UF2_FAMILY_ID = 0xF71C0343
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "ECDSA_KEY",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
12: "KM_INIT_KEY",
}
def get_chip_description(self): def get_chip_description(self):
chip_name = { chip_name = {
0: "ESP32-C5", 0: "ESP32-C5",

View File

@@ -4,6 +4,7 @@
import struct import struct
import time import time
from typing import Dict
from .esp32c6 import ESP32C6ROM from .esp32c6 import ESP32C6ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -41,6 +42,23 @@ class ESP32C5BETA3ROM(ESP32C6ROM):
[0x600FE000, 0x60100000, "MEM_INTERNAL2"], [0x600FE000, 0x60100000, "MEM_INTERNAL2"],
] ]
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "ECDSA_KEY",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
12: "KM_INIT_KEY",
}
def get_chip_description(self): def get_chip_description(self):
chip_name = { chip_name = {
0: "ESP32-C5 beta3 (QFN40)", 0: "ESP32-C5 beta3 (QFN40)",

View File

@@ -161,8 +161,10 @@ class ESP32C6ROM(ESP32C3ROM):
) )
def get_key_block_purpose(self, key_block): def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5: if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError("Valid key block numbers must be in range 0-5") raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, shift = [ reg, shift = [
(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT),
@@ -176,7 +178,9 @@ class ESP32C6ROM(ESP32C3ROM):
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):
# Need to see an AES-128 key # Need to see an AES-128 key
purposes = [self.get_key_block_purpose(b) for b in range(6)] purposes = [
self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1)
]
return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes) return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes)

View File

@@ -3,6 +3,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
import struct import struct
from typing import Dict
from .esp32c6 import ESP32C6ROM from .esp32c6 import ESP32C6ROM
@@ -60,6 +61,26 @@ class ESP32C61ROM(ESP32C6ROM):
UF2_FAMILY_ID = 0x77D850C4 UF2_FAMILY_ID = 0x77D850C4
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "ECDSA_KEY",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
12: "KM_INIT_KEY",
13: "XTS_AES_256_KEY_1_PSRAM",
14: "XTS_AES_256_KEY_2_PSRAM",
15: "XTS_AES_128_KEY_PSRAM",
}
def get_chip_description(self): def get_chip_description(self):
chip_name = { chip_name = {
0: "ESP32-C61", 0: "ESP32-C61",

View File

@@ -3,6 +3,8 @@
# #
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
from typing import Dict
from .esp32c6 import ESP32C6ROM from .esp32c6 import ESP32C6ROM
from ..util import FatalError from ..util import FatalError
@@ -32,6 +34,22 @@ class ESP32H2ROM(ESP32C6ROM):
UF2_FAMILY_ID = 0x332726F6 UF2_FAMILY_ID = 0x332726F6
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "ECDSA_KEY",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 4 num_word = 4
return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
import struct import struct
from typing import Dict
from .esp32c3 import ESP32C3ROM from .esp32c3 import ESP32C3ROM
from ..util import FatalError, NotImplementedInROMError from ..util import FatalError, NotImplementedInROMError
@@ -77,6 +78,21 @@ class ESP32H2BETA1ROM(ESP32C3ROM):
"12m": 0x2, "12m": 0x2,
} }
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "ECDSA_KEY",
2: "RESERVED",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 4 num_word = 4
return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x07
@@ -121,8 +137,10 @@ class ESP32H2BETA1ROM(ESP32C3ROM):
return None # doesn't exist on ESP32-H2 return None # doesn't exist on ESP32-H2
def get_key_block_purpose(self, key_block): def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5: if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError("Valid key block numbers must be in range 0-5") raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, shift = [ reg, shift = [
(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT),
@@ -136,7 +154,9 @@ class ESP32H2BETA1ROM(ESP32C3ROM):
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):
# Need to see an AES-128 key # Need to see an AES-128 key
purposes = [self.get_key_block_purpose(b) for b in range(6)] purposes = [
self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1)
]
return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes) return any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes)

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
import struct import struct
from typing import Dict
from .esp32 import ESP32ROM from .esp32 import ESP32ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -85,6 +86,23 @@ class ESP32P4ROM(ESP32ROM):
UF2_FAMILY_ID = 0x3D308E94 UF2_FAMILY_ID = 0x3D308E94
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "ECDSA_KEY",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
12: "KM_INIT_KEY",
}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 2 num_word = 2
return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 27) & 0x07 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 27) & 0x07
@@ -139,8 +157,10 @@ class ESP32P4ROM(ESP32ROM):
) )
def get_key_block_purpose(self, key_block): def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5: if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError("Valid key block numbers must be in range 0-5") raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, shift = [ reg, shift = [
(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT),
@@ -154,7 +174,9 @@ class ESP32P4ROM(ESP32ROM):
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):
# Need to see either an AES-128 key or two AES-256 keys # Need to see either an AES-128 key or two AES-256 keys
purposes = [self.get_key_block_purpose(b) for b in range(6)] purposes = [
self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1)
]
if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes):
return True return True

View File

@@ -5,6 +5,7 @@
import os import os
import struct import struct
from typing import Dict
from .esp32 import ESP32ROM from .esp32 import ESP32ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -107,6 +108,22 @@ class ESP32S2ROM(ESP32ROM):
UF2_FAMILY_ID = 0xBFDD4EEE UF2_FAMILY_ID = 0xBFDD4EEE
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "RESERVED",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 4 num_word = 4
return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x0F return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 0) & 0x0F
@@ -224,8 +241,10 @@ class ESP32S2ROM(ESP32ROM):
) )
def get_key_block_purpose(self, key_block): def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5: if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError("Valid key block numbers must be in range 0-5") raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, shift = [ reg, shift = [
(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT),
@@ -239,7 +258,9 @@ class ESP32S2ROM(ESP32ROM):
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):
# Need to see either an AES-128 key or two AES-256 keys # Need to see either an AES-128 key or two AES-256 keys
purposes = [self.get_key_block_purpose(b) for b in range(6)] purposes = [
self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1)
]
if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes):
return True return True

View File

@@ -5,6 +5,7 @@
import os import os
import struct import struct
from typing import Dict
from .esp32 import ESP32ROM from .esp32 import ESP32ROM
from ..loader import ESPLoader from ..loader import ESPLoader
@@ -123,6 +124,22 @@ class ESP32S3ROM(ESP32ROM):
UF2_FAMILY_ID = 0xC47E5767 UF2_FAMILY_ID = 0xC47E5767
EFUSE_MAX_KEY = 5
KEY_PURPOSES: Dict[int, str] = {
0: "USER/EMPTY",
1: "RESERVED",
2: "XTS_AES_256_KEY_1",
3: "XTS_AES_256_KEY_2",
4: "XTS_AES_128_KEY",
5: "HMAC_DOWN_ALL",
6: "HMAC_DOWN_JTAG",
7: "HMAC_DOWN_DIGITAL_SIGNATURE",
8: "HMAC_UP",
9: "SECURE_BOOT_DIGEST0",
10: "SECURE_BOOT_DIGEST1",
11: "SECURE_BOOT_DIGEST2",
}
def get_pkg_version(self): def get_pkg_version(self):
num_word = 3 num_word = 3
return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07 return (self.read_reg(self.EFUSE_BLOCK1_ADDR + (4 * num_word)) >> 21) & 0x07
@@ -227,8 +244,10 @@ class ESP32S3ROM(ESP32ROM):
return None # doesn't exist on ESP32-S3 return None # doesn't exist on ESP32-S3
def get_key_block_purpose(self, key_block): def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5: if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError("Valid key block numbers must be in range 0-5") raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, shift = [ reg, shift = [
(self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT), (self.EFUSE_PURPOSE_KEY0_REG, self.EFUSE_PURPOSE_KEY0_SHIFT),
@@ -242,7 +261,9 @@ class ESP32S3ROM(ESP32ROM):
def is_flash_encryption_key_valid(self): def is_flash_encryption_key_valid(self):
# Need to see either an AES-128 key or two AES-256 keys # Need to see either an AES-128 key or two AES-256 keys
purposes = [self.get_key_block_purpose(b) for b in range(6)] purposes = [
self.get_key_block_purpose(b) for b in range(self.EFUSE_MAX_KEY + 1)
]
if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes): if any(p == self.PURPOSE_VAL_XTS_AES128_KEY for p in purposes):
return True return True

View File

@@ -670,7 +670,8 @@ class TestSecurityInfo(EsptoolTestCase):
res = self.run_esptool("get_security_info") res = self.run_esptool("get_security_info")
assert "Flags" in res assert "Flags" in res
assert "Crypt Count" in res assert "Crypt Count" in res
assert "Key Purposes" in res if arg_chip != "esp32c2":
assert "Key Purposes" in res
if arg_chip != "esp32s2": if arg_chip != "esp32s2":
try: try:
esp = esptool.get_default_connected_device( esp = esptool.get_default_connected_device(