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("=" * len(title))
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:
print("Chip ID: {}".format(si["chip_id"]))
print("API Version: {}".format(si["api_version"]))

View File

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

View File

@@ -5,6 +5,7 @@
import struct
import time
from typing import Dict
from .esp32c3 import ESP32C3ROM
from ..loader import ESPLoader
@@ -64,6 +65,8 @@ class ESP32C2ROM(ESP32C3ROM):
UF2_FAMILY_ID = 0x2B88D29C
KEY_PURPOSES: Dict[int, str] = {}
def get_pkg_version(self):
num_word = 1
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
import struct
from typing import Dict
from .esp32 import ESP32ROM
from ..loader import ESPLoader
@@ -99,6 +100,20 @@ class ESP32C3ROM(ESP32ROM):
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):
num_word = 3
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):
if key_block < 0 or key_block > 5:
raise FatalError("Valid key block numbers must be in range 0-5")
if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, 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):
# 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)

View File

@@ -4,6 +4,7 @@
import struct
import time
from typing import Dict
from .esp32c6 import ESP32C6ROM
from ..loader import ESPLoader
@@ -52,6 +53,23 @@ class ESP32C5ROM(ESP32C6ROM):
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):
chip_name = {
0: "ESP32-C5",

View File

@@ -4,6 +4,7 @@
import struct
import time
from typing import Dict
from .esp32c6 import ESP32C6ROM
from ..loader import ESPLoader
@@ -41,6 +42,23 @@ class ESP32C5BETA3ROM(ESP32C6ROM):
[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):
chip_name = {
0: "ESP32-C5 beta3 (QFN40)",

View File

@@ -161,8 +161,10 @@ class ESP32C6ROM(ESP32C3ROM):
)
def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5:
raise FatalError("Valid key block numbers must be in range 0-5")
if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, 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):
# 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)

View File

@@ -3,6 +3,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import struct
from typing import Dict
from .esp32c6 import ESP32C6ROM
@@ -60,6 +61,26 @@ class ESP32C61ROM(ESP32C6ROM):
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):
chip_name = {
0: "ESP32-C61",

View File

@@ -3,6 +3,8 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
from typing import Dict
from .esp32c6 import ESP32C6ROM
from ..util import FatalError
@@ -32,6 +34,22 @@ class ESP32H2ROM(ESP32C6ROM):
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):
num_word = 4
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
import struct
from typing import Dict
from .esp32c3 import ESP32C3ROM
from ..util import FatalError, NotImplementedInROMError
@@ -77,6 +78,21 @@ class ESP32H2BETA1ROM(ESP32C3ROM):
"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):
num_word = 4
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
def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5:
raise FatalError("Valid key block numbers must be in range 0-5")
if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, 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):
# 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)

View File

@@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
import struct
from typing import Dict
from .esp32 import ESP32ROM
from ..loader import ESPLoader
@@ -85,6 +86,23 @@ class ESP32P4ROM(ESP32ROM):
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):
num_word = 2
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):
if key_block < 0 or key_block > 5:
raise FatalError("Valid key block numbers must be in range 0-5")
if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, 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):
# 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):
return True

View File

@@ -5,6 +5,7 @@
import os
import struct
from typing import Dict
from .esp32 import ESP32ROM
from ..loader import ESPLoader
@@ -107,6 +108,22 @@ class ESP32S2ROM(ESP32ROM):
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):
num_word = 4
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):
if key_block < 0 or key_block > 5:
raise FatalError("Valid key block numbers must be in range 0-5")
if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, 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):
# 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):
return True

View File

@@ -5,6 +5,7 @@
import os
import struct
from typing import Dict
from .esp32 import ESP32ROM
from ..loader import ESPLoader
@@ -123,6 +124,22 @@ class ESP32S3ROM(ESP32ROM):
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):
num_word = 3
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
def get_key_block_purpose(self, key_block):
if key_block < 0 or key_block > 5:
raise FatalError("Valid key block numbers must be in range 0-5")
if key_block < 0 or key_block > self.EFUSE_MAX_KEY:
raise FatalError(
f"Valid key block numbers must be in range 0-{self.EFUSE_MAX_KEY}"
)
reg, 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):
# 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):
return True

View File

@@ -670,7 +670,8 @@ class TestSecurityInfo(EsptoolTestCase):
res = self.run_esptool("get_security_info")
assert "Flags" 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":
try:
esp = esptool.get_default_connected_device(