mirror of
https://github.com/espressif/esptool.git
synced 2025-10-20 04:54:31 +08:00
feat(espsecure): Add support for secure boot v2 using ECDSA-P384 signatures
This commit is contained in:
@@ -31,9 +31,14 @@ SIG_BLOCK_MAGIC = 0xE7
|
|||||||
SIG_BLOCK_VERSION_RSA = 0x02
|
SIG_BLOCK_VERSION_RSA = 0x02
|
||||||
SIG_BLOCK_VERSION_ECDSA = 0x03
|
SIG_BLOCK_VERSION_ECDSA = 0x03
|
||||||
|
|
||||||
|
# SHA scheme used in Secure Boot V2 ECDSA signature blocks
|
||||||
|
ECDSA_SHA_256 = 0x0
|
||||||
|
ECDSA_SHA_384 = 0x1
|
||||||
|
|
||||||
# Curve IDs used in Secure Boot V2 ECDSA signature blocks
|
# Curve IDs used in Secure Boot V2 ECDSA signature blocks
|
||||||
CURVE_ID_P192 = 1
|
CURVE_ID_P192 = 1
|
||||||
CURVE_ID_P256 = 2
|
CURVE_ID_P256 = 2
|
||||||
|
CURVE_ID_P384 = 3
|
||||||
|
|
||||||
SECTOR_SIZE = 4096
|
SECTOR_SIZE = 4096
|
||||||
SIG_BLOCK_SIZE = (
|
SIG_BLOCK_SIZE = (
|
||||||
@@ -182,23 +187,21 @@ def generate_signing_key(args):
|
|||||||
)
|
)
|
||||||
with open(args.keyfile, "wb") as f:
|
with open(args.keyfile, "wb") as f:
|
||||||
f.write(private_key)
|
f.write(private_key)
|
||||||
print("RSA 3072 private key in PEM format written to %s" % args.keyfile)
|
print(f"RSA 3072 private key in PEM format written to {args.keyfile}")
|
||||||
elif args.scheme == "ecdsa192":
|
elif args.scheme == "ecdsa192":
|
||||||
"""Generate a ECDSA 192 signing key for signing secure boot images"""
|
"""Generate a ECDSA 192 signing key for signing secure boot images"""
|
||||||
_generate_ecdsa_signing_key(ecdsa.NIST192p, args.keyfile)
|
_generate_ecdsa_signing_key(ecdsa.NIST192p, args.keyfile)
|
||||||
print(
|
print(f"ECDSA NIST192p private key in PEM format written to {args.keyfile}")
|
||||||
"ECDSA NIST192p private key in PEM format written to %s" % args.keyfile
|
|
||||||
)
|
|
||||||
elif args.scheme == "ecdsa256":
|
elif args.scheme == "ecdsa256":
|
||||||
"""Generate a ECDSA 256 signing key for signing secure boot images"""
|
"""Generate a ECDSA 256 signing key for signing secure boot images"""
|
||||||
_generate_ecdsa_signing_key(ecdsa.NIST256p, args.keyfile)
|
_generate_ecdsa_signing_key(ecdsa.NIST256p, args.keyfile)
|
||||||
print(
|
print(f"ECDSA NIST256p private key in PEM format written to {args.keyfile}")
|
||||||
"ECDSA NIST256p private key in PEM format written to %s" % args.keyfile
|
elif args.scheme == "ecdsa384":
|
||||||
)
|
"""Generate a ECDSA 384 signing key for signing secure boot images"""
|
||||||
|
_generate_ecdsa_signing_key(ecdsa.NIST384p, args.keyfile)
|
||||||
|
print(f"ECDSA NIST384p private key in PEM format written to {args.keyfile}")
|
||||||
else:
|
else:
|
||||||
raise esptool.FatalError(
|
raise esptool.FatalError("ERROR: Unsupported signing scheme {args.scheme}")
|
||||||
"ERROR: Unsupported signing scheme (%s)" % args.scheme
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def load_ecdsa_signing_key(keyfile):
|
def load_ecdsa_signing_key(keyfile):
|
||||||
@@ -260,12 +263,10 @@ def _load_sbv2_signing_key(keydata):
|
|||||||
)
|
)
|
||||||
return sk
|
return sk
|
||||||
if isinstance(sk, ec.EllipticCurvePrivateKey):
|
if isinstance(sk, ec.EllipticCurvePrivateKey):
|
||||||
if not (
|
if not isinstance(sk.curve, (ec.SECP192R1, ec.SECP256R1, ec.SECP384R1)):
|
||||||
isinstance(sk.curve, ec.SECP192R1) or isinstance(sk.curve, ec.SECP256R1)
|
|
||||||
):
|
|
||||||
raise esptool.FatalError(
|
raise esptool.FatalError(
|
||||||
"Key file uses incorrect curve. Secure Boot V2 + ECDSA only supports "
|
"Key file uses incorrect curve. Secure Boot V2 + ECDSA only supports "
|
||||||
"NIST192p, NIST256p (aka prime192v1, prime256v1)"
|
"NIST192p, NIST256p, NIST384p (aka prime192v1 / secp192r1, prime256v1 / secp256r1, secp384r1)"
|
||||||
)
|
)
|
||||||
return sk
|
return sk
|
||||||
|
|
||||||
@@ -285,12 +286,10 @@ def _load_sbv2_pub_key(keydata):
|
|||||||
)
|
)
|
||||||
return vk
|
return vk
|
||||||
if isinstance(vk, ec.EllipticCurvePublicKey):
|
if isinstance(vk, ec.EllipticCurvePublicKey):
|
||||||
if not (
|
if not isinstance(vk.curve, (ec.SECP192R1, ec.SECP256R1, ec.SECP384R1)):
|
||||||
isinstance(vk.curve, ec.SECP192R1) or isinstance(vk.curve, ec.SECP256R1)
|
|
||||||
):
|
|
||||||
raise esptool.FatalError(
|
raise esptool.FatalError(
|
||||||
"Key file uses incorrect curve. Secure Boot V2 + ECDSA only supports "
|
"Key file uses incorrect curve. Secure Boot V2 + ECDSA only supports "
|
||||||
"NIST192p, NIST256p (aka prime192v1, prime256v1)"
|
"NIST192p, NIST256p, NIST384p (aka prime192v1 / secp192r1, prime256v1 / secp256r1, secp384r1)"
|
||||||
)
|
)
|
||||||
return vk
|
return vk
|
||||||
|
|
||||||
@@ -338,7 +337,7 @@ def _microecc_format(a, b, curve_len):
|
|||||||
"""
|
"""
|
||||||
byte_len = int(curve_len / 8)
|
byte_len = int(curve_len / 8)
|
||||||
ab = int_to_bytes(a, byte_len)[::-1] + int_to_bytes(b, byte_len)[::-1]
|
ab = int_to_bytes(a, byte_len)[::-1] + int_to_bytes(b, byte_len)[::-1]
|
||||||
assert len(ab) == 48 or len(ab) == 64
|
assert len(ab) in [48, 64, 96]
|
||||||
return ab
|
return ab
|
||||||
|
|
||||||
|
|
||||||
@@ -402,7 +401,7 @@ def sign_secure_boot_v1(args):
|
|||||||
def sign_secure_boot_v2(args):
|
def sign_secure_boot_v2(args):
|
||||||
"""
|
"""
|
||||||
Sign a firmware app image with an RSA private key using RSA-PSS,
|
Sign a firmware app image with an RSA private key using RSA-PSS,
|
||||||
or ECDSA private key using P192 or P256.
|
or ECDSA private key using P192 or P256 or P384.
|
||||||
|
|
||||||
Write output file with a Secure Boot V2 header appended.
|
Write output file with a Secure Boot V2 header appended.
|
||||||
"""
|
"""
|
||||||
@@ -496,20 +495,16 @@ def sign_secure_boot_v2(args):
|
|||||||
)
|
)
|
||||||
|
|
||||||
print(f"{key_count} signing key(s) found.")
|
print(f"{key_count} signing key(s) found.")
|
||||||
# Calculate digest of data file
|
|
||||||
digest = hashlib.sha256()
|
|
||||||
digest.update(contents)
|
|
||||||
digest = digest.digest()
|
|
||||||
|
|
||||||
# Generate signature block using pre-calculated signatures
|
# Generate signature block using pre-calculated signatures
|
||||||
if signature:
|
if signature:
|
||||||
signature_block = generate_signature_block_using_pre_calculated_signature(
|
signature_block = generate_signature_block_using_pre_calculated_signature(
|
||||||
signature, pub_key, digest
|
signature, pub_key, contents
|
||||||
)
|
)
|
||||||
# Generate signature block by signing using private keys
|
# Generate signature block by signing using private keys
|
||||||
else:
|
else:
|
||||||
signature_block = generate_signature_block_using_private_key(
|
signature_block = generate_signature_block_using_private_key(
|
||||||
args.keyfile, digest
|
args.keyfile, contents
|
||||||
)
|
)
|
||||||
|
|
||||||
if signature_block is None or len(signature_block) == 0:
|
if signature_block is None or len(signature_block) == 0:
|
||||||
@@ -560,13 +555,17 @@ def generate_signature_using_hsm(config, contents):
|
|||||||
return [temp_signature_file]
|
return [temp_signature_file]
|
||||||
|
|
||||||
|
|
||||||
def generate_signature_block_using_pre_calculated_signature(signature, pub_key, digest):
|
def generate_signature_block_using_pre_calculated_signature(
|
||||||
|
signature, pub_key, contents
|
||||||
|
):
|
||||||
signature_blocks = b""
|
signature_blocks = b""
|
||||||
for sig, pk in zip(signature, pub_key):
|
for sig, pk in zip(signature, pub_key):
|
||||||
try:
|
try:
|
||||||
public_key = _get_sbv2_pub_key(pk)
|
public_key = _get_sbv2_pub_key(pk)
|
||||||
signature = sig.read()
|
signature = sig.read()
|
||||||
if isinstance(public_key, rsa.RSAPublicKey):
|
if isinstance(public_key, rsa.RSAPublicKey):
|
||||||
|
# Calculate digest of data file
|
||||||
|
digest = _sha256_digest(contents)
|
||||||
# RSA signature
|
# RSA signature
|
||||||
rsa_primitives = _get_sbv2_rsa_primitives(public_key)
|
rsa_primitives = _get_sbv2_rsa_primitives(public_key)
|
||||||
# Verify the signature
|
# Verify the signature
|
||||||
@@ -586,15 +585,24 @@ def generate_signature_block_using_pre_calculated_signature(signature, pub_key,
|
|||||||
if isinstance(numbers.curve, ec.SECP192R1):
|
if isinstance(numbers.curve, ec.SECP192R1):
|
||||||
curve_len = 192
|
curve_len = 192
|
||||||
curve_id = CURVE_ID_P192
|
curve_id = CURVE_ID_P192
|
||||||
|
hash_type = hashes.SHA256()
|
||||||
|
digest = _sha256_digest(contents)
|
||||||
elif isinstance(numbers.curve, ec.SECP256R1):
|
elif isinstance(numbers.curve, ec.SECP256R1):
|
||||||
curve_len = 256
|
curve_len = 256
|
||||||
curve_id = CURVE_ID_P256
|
curve_id = CURVE_ID_P256
|
||||||
|
hash_type = hashes.SHA256()
|
||||||
|
digest = _sha256_digest(contents)
|
||||||
|
elif isinstance(numbers.curve, ec.SECP384R1):
|
||||||
|
curve_len = 384
|
||||||
|
curve_id = CURVE_ID_P384
|
||||||
|
hash_type = hashes.SHA384()
|
||||||
|
digest = _sha384_digest(contents)
|
||||||
else:
|
else:
|
||||||
raise esptool.FatalError("Invalid ECDSA curve instance.")
|
raise esptool.FatalError("Invalid ECDSA curve instance.")
|
||||||
|
|
||||||
# Verify the signature
|
# Verify the signature
|
||||||
public_key.verify(
|
public_key.verify(
|
||||||
signature, digest, ec.ECDSA(utils.Prehashed(hashes.SHA256()))
|
signature, digest, ec.ECDSA(utils.Prehashed(hash_type))
|
||||||
)
|
)
|
||||||
|
|
||||||
pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len)
|
pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len)
|
||||||
@@ -619,13 +627,14 @@ def generate_signature_block_using_pre_calculated_signature(signature, pub_key,
|
|||||||
return signature_blocks
|
return signature_blocks
|
||||||
|
|
||||||
|
|
||||||
def generate_signature_block_using_private_key(keyfiles, digest):
|
def generate_signature_block_using_private_key(keyfiles, contents):
|
||||||
signature_blocks = b""
|
signature_blocks = b""
|
||||||
for keyfile in keyfiles:
|
for keyfile in keyfiles:
|
||||||
private_key = _load_sbv2_signing_key(keyfile.read())
|
private_key = _load_sbv2_signing_key(keyfile.read())
|
||||||
|
|
||||||
# Sign
|
# Sign
|
||||||
if isinstance(private_key, rsa.RSAPrivateKey):
|
if isinstance(private_key, rsa.RSAPrivateKey):
|
||||||
|
digest = _sha256_digest(contents)
|
||||||
# RSA signature
|
# RSA signature
|
||||||
signature = private_key.sign(
|
signature = private_key.sign(
|
||||||
digest,
|
digest,
|
||||||
@@ -640,21 +649,28 @@ def generate_signature_block_using_private_key(keyfiles, digest):
|
|||||||
digest, rsa_primitives, signature
|
digest, rsa_primitives, signature
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# ECDSA signature
|
|
||||||
signature = private_key.sign(
|
|
||||||
digest, ec.ECDSA(utils.Prehashed(hashes.SHA256()))
|
|
||||||
)
|
|
||||||
|
|
||||||
numbers = private_key.public_key().public_numbers()
|
numbers = private_key.public_key().public_numbers()
|
||||||
if isinstance(private_key.curve, ec.SECP192R1):
|
if isinstance(private_key.curve, ec.SECP192R1):
|
||||||
curve_len = 192
|
curve_len = 192
|
||||||
curve_id = CURVE_ID_P192
|
curve_id = CURVE_ID_P192
|
||||||
|
hash_type = hashes.SHA256()
|
||||||
|
digest = _sha256_digest(contents)
|
||||||
elif isinstance(numbers.curve, ec.SECP256R1):
|
elif isinstance(numbers.curve, ec.SECP256R1):
|
||||||
curve_len = 256
|
curve_len = 256
|
||||||
curve_id = CURVE_ID_P256
|
curve_id = CURVE_ID_P256
|
||||||
|
hash_type = hashes.SHA256()
|
||||||
|
digest = _sha256_digest(contents)
|
||||||
|
elif isinstance(numbers.curve, ec.SECP384R1):
|
||||||
|
curve_len = 384
|
||||||
|
curve_id = CURVE_ID_P384
|
||||||
|
hash_type = hashes.SHA384()
|
||||||
|
digest = _sha384_digest(contents)
|
||||||
else:
|
else:
|
||||||
raise esptool.FatalError("Invalid ECDSA curve instance.")
|
raise esptool.FatalError("Invalid ECDSA curve instance.")
|
||||||
|
|
||||||
|
# ECDSA signatures
|
||||||
|
signature = private_key.sign(digest, ec.ECDSA(utils.Prehashed(hash_type)))
|
||||||
|
|
||||||
pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len)
|
pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len)
|
||||||
|
|
||||||
r, s = utils.decode_dss_signature(signature)
|
r, s = utils.decode_dss_signature(signature)
|
||||||
@@ -703,15 +719,34 @@ def generate_ecdsa_signature_block(digest, curve_id, pubkey_point, signature_rs)
|
|||||||
# block is padded out to the much larger size
|
# block is padded out to the much larger size
|
||||||
# of the RSA version of this structure
|
# of the RSA version of this structure
|
||||||
"""
|
"""
|
||||||
signature_block = struct.pack(
|
|
||||||
"<BBxx32sB64s64s1031x",
|
if curve_id in [CURVE_ID_P192, CURVE_ID_P256]:
|
||||||
SIG_BLOCK_MAGIC,
|
signature_block = struct.pack(
|
||||||
SIG_BLOCK_VERSION_ECDSA,
|
"<BBBx32sB64s64s1031x",
|
||||||
digest,
|
SIG_BLOCK_MAGIC,
|
||||||
curve_id,
|
SIG_BLOCK_VERSION_ECDSA,
|
||||||
pubkey_point,
|
ECDSA_SHA_256,
|
||||||
signature_rs,
|
digest,
|
||||||
)
|
curve_id,
|
||||||
|
pubkey_point,
|
||||||
|
signature_rs,
|
||||||
|
)
|
||||||
|
elif curve_id == CURVE_ID_P384:
|
||||||
|
signature_block = struct.pack(
|
||||||
|
"<BBBx48sB96s96s951x",
|
||||||
|
SIG_BLOCK_MAGIC,
|
||||||
|
SIG_BLOCK_VERSION_ECDSA,
|
||||||
|
ECDSA_SHA_384,
|
||||||
|
digest,
|
||||||
|
curve_id,
|
||||||
|
pubkey_point,
|
||||||
|
signature_rs,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise esptool.FatalError(
|
||||||
|
"Invalid ECDSA curve ID detected while generating ECDSA signature block."
|
||||||
|
)
|
||||||
|
|
||||||
return signature_block
|
return signature_block
|
||||||
|
|
||||||
|
|
||||||
@@ -818,10 +853,6 @@ def verify_signature_v2(args):
|
|||||||
"Invalid datafile. Data size should be non-zero & a multiple of 4096."
|
"Invalid datafile. Data size should be non-zero & a multiple of 4096."
|
||||||
)
|
)
|
||||||
|
|
||||||
digest = digest = hashlib.sha256()
|
|
||||||
digest.update(image_content[:-SECTOR_SIZE])
|
|
||||||
digest = digest.digest()
|
|
||||||
|
|
||||||
valid = False
|
valid = False
|
||||||
|
|
||||||
for sig_blk_num in range(SIG_BLOCK_MAX_COUNT):
|
for sig_blk_num in range(SIG_BLOCK_MAX_COUNT):
|
||||||
@@ -829,7 +860,14 @@ def verify_signature_v2(args):
|
|||||||
if sig_blk is None:
|
if sig_blk is None:
|
||||||
print(f"Signature block {sig_blk_num} invalid. Skipping.")
|
print(f"Signature block {sig_blk_num} invalid. Skipping.")
|
||||||
continue
|
continue
|
||||||
_, version, blk_digest = struct.unpack("<BBxx32s", sig_blk[:36])
|
_, version, ecdsa_sha_version = struct.unpack("<BBBx", sig_blk[:4])
|
||||||
|
|
||||||
|
if version == SIG_BLOCK_VERSION_ECDSA and ecdsa_sha_version == ECDSA_SHA_384:
|
||||||
|
blk_digest = struct.unpack("<48s", sig_blk[4:52])[0]
|
||||||
|
digest = _sha384_digest(image_content[:-SECTOR_SIZE])
|
||||||
|
else:
|
||||||
|
blk_digest = struct.unpack("<32s", sig_blk[4:36])[0]
|
||||||
|
digest = _sha256_digest(image_content[:-SECTOR_SIZE])
|
||||||
|
|
||||||
if blk_digest != digest:
|
if blk_digest != digest:
|
||||||
raise esptool.FatalError(
|
raise esptool.FatalError(
|
||||||
@@ -849,22 +887,34 @@ def verify_signature_v2(args):
|
|||||||
utils.Prehashed(hashes.SHA256()),
|
utils.Prehashed(hashes.SHA256()),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
curve_id, _pubkey, encoded_rs = struct.unpack(
|
if ecdsa_sha_version == ECDSA_SHA_256:
|
||||||
"B64s64s1031x4x16x", sig_blk[36:]
|
curve_id, _pubkey, encoded_rs = struct.unpack(
|
||||||
)
|
"B64s64s1031x4x16x", sig_blk[36:]
|
||||||
|
)
|
||||||
|
elif ecdsa_sha_version == ECDSA_SHA_384:
|
||||||
|
curve_id, _pubkey, encoded_rs = struct.unpack(
|
||||||
|
"B96s96s951x4x16x", sig_blk[52:]
|
||||||
|
)
|
||||||
|
|
||||||
assert curve_id in (CURVE_ID_P192, CURVE_ID_P256)
|
assert curve_id in (CURVE_ID_P192, CURVE_ID_P256, CURVE_ID_P384)
|
||||||
|
|
||||||
keylen = (
|
# length of each number in the keypair
|
||||||
24 if curve_id == CURVE_ID_P192 else 32
|
if curve_id == CURVE_ID_P192:
|
||||||
) # length of each number in the keypair
|
keylen = 24
|
||||||
|
hash_type = hashes.SHA256()
|
||||||
|
elif curve_id == CURVE_ID_P256:
|
||||||
|
keylen = 32
|
||||||
|
hash_type = hashes.SHA256()
|
||||||
|
elif curve_id == CURVE_ID_P384:
|
||||||
|
keylen = 48
|
||||||
|
hash_type = hashes.SHA384()
|
||||||
|
|
||||||
r = int.from_bytes(encoded_rs[:keylen], "little")
|
r = int.from_bytes(encoded_rs[:keylen], "little")
|
||||||
s = int.from_bytes(encoded_rs[keylen : keylen * 2], "little")
|
s = int.from_bytes(encoded_rs[keylen : keylen * 2], "little")
|
||||||
|
|
||||||
signature = utils.encode_dss_signature(r, s)
|
signature = utils.encode_dss_signature(r, s)
|
||||||
|
|
||||||
vk.verify(signature, digest, ec.ECDSA(utils.Prehashed(hashes.SHA256())))
|
vk.verify(signature, digest, ec.ECDSA(utils.Prehashed(hash_type)))
|
||||||
|
|
||||||
key_type = "RSA" if isinstance(vk, rsa.RSAPublicKey) else "ECDSA"
|
key_type = "RSA" if isinstance(vk, rsa.RSAPublicKey) else "ECDSA"
|
||||||
|
|
||||||
@@ -937,6 +987,13 @@ def _sha256_digest(data):
|
|||||||
return digest.digest()
|
return digest.digest()
|
||||||
|
|
||||||
|
|
||||||
|
def _sha384_digest(contents):
|
||||||
|
# Calculate digest of data file
|
||||||
|
digest = hashlib.sha384()
|
||||||
|
digest.update(contents)
|
||||||
|
return digest.digest()
|
||||||
|
|
||||||
|
|
||||||
def signature_info_v2(args):
|
def signature_info_v2(args):
|
||||||
"""
|
"""
|
||||||
Validates the signature block and prints the RSA/ECDSA public key
|
Validates the signature block and prints the RSA/ECDSA public key
|
||||||
@@ -950,8 +1007,6 @@ def signature_info_v2(args):
|
|||||||
"Invalid datafile. Data size should be non-zero & a multiple of 4096."
|
"Invalid datafile. Data size should be non-zero & a multiple of 4096."
|
||||||
)
|
)
|
||||||
|
|
||||||
digest = _sha256_digest(image_content[:-SECTOR_SIZE])
|
|
||||||
|
|
||||||
for sig_blk_num in range(SIG_BLOCK_MAX_COUNT):
|
for sig_blk_num in range(SIG_BLOCK_MAX_COUNT):
|
||||||
sig_blk = validate_signature_block(image_content, sig_blk_num)
|
sig_blk = validate_signature_block(image_content, sig_blk_num)
|
||||||
if sig_blk is None:
|
if sig_blk is None:
|
||||||
@@ -961,7 +1016,15 @@ def signature_info_v2(args):
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
sig_data = struct.unpack("<BBxx32s384sI384sI384sI16x", sig_blk)
|
_, version, ecdsa_sha_version = struct.unpack("<BBBx", sig_blk[:4])
|
||||||
|
|
||||||
|
if version == SIG_BLOCK_VERSION_ECDSA and ecdsa_sha_version == ECDSA_SHA_384:
|
||||||
|
sig_data = struct.unpack("<BBxx48s1164x", sig_blk)
|
||||||
|
digest = _sha384_digest(image_content[:-SECTOR_SIZE])
|
||||||
|
else:
|
||||||
|
sig_data = struct.unpack("<BBxx32s1180x", sig_blk)
|
||||||
|
digest = _sha256_digest(image_content[:-SECTOR_SIZE])
|
||||||
|
|
||||||
if sig_data[2] != digest:
|
if sig_data[2] != digest:
|
||||||
raise esptool.FatalError(
|
raise esptool.FatalError(
|
||||||
"Digest in signature block %d doesn't match the image digest."
|
"Digest in signature block %d doesn't match the image digest."
|
||||||
@@ -973,7 +1036,10 @@ def signature_info_v2(args):
|
|||||||
if sig_data[1] == SIG_BLOCK_VERSION_RSA:
|
if sig_data[1] == SIG_BLOCK_VERSION_RSA:
|
||||||
key_digest = _sha256_digest(sig_blk[36:812])
|
key_digest = _sha256_digest(sig_blk[36:812])
|
||||||
elif sig_data[1] == SIG_BLOCK_VERSION_ECDSA:
|
elif sig_data[1] == SIG_BLOCK_VERSION_ECDSA:
|
||||||
key_digest = _sha256_digest(sig_blk[36:101])
|
if ecdsa_sha_version == ECDSA_SHA_384:
|
||||||
|
key_digest = _sha256_digest(sig_blk[52:149])
|
||||||
|
else:
|
||||||
|
key_digest = _sha256_digest(sig_blk[36:101])
|
||||||
else:
|
else:
|
||||||
raise esptool.FatalError(
|
raise esptool.FatalError(
|
||||||
"Unsupported scheme in signature block %d" % (sig_blk_num)
|
"Unsupported scheme in signature block %d" % (sig_blk_num)
|
||||||
@@ -1009,16 +1075,27 @@ def _digest_sbv2_public_key(keyfile):
|
|||||||
if isinstance(public_key.curve, ec.SECP192R1):
|
if isinstance(public_key.curve, ec.SECP192R1):
|
||||||
curve_len = 192
|
curve_len = 192
|
||||||
curve_id = CURVE_ID_P192
|
curve_id = CURVE_ID_P192
|
||||||
else:
|
elif isinstance(public_key.curve, ec.SECP256R1):
|
||||||
curve_len = 256
|
curve_len = 256
|
||||||
curve_id = CURVE_ID_P256
|
curve_id = CURVE_ID_P256
|
||||||
|
elif isinstance(public_key.curve, ec.SECP384R1):
|
||||||
|
curve_len = 384
|
||||||
|
curve_id = CURVE_ID_P384
|
||||||
|
|
||||||
pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len)
|
pubkey_point = _microecc_format(numbers.x, numbers.y, curve_len)
|
||||||
|
|
||||||
binary_format = struct.pack(
|
if curve_id == CURVE_ID_P384:
|
||||||
"<B64s",
|
binary_format = struct.pack(
|
||||||
curve_id,
|
"<B96s",
|
||||||
pubkey_point,
|
curve_id,
|
||||||
)
|
pubkey_point,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
binary_format = struct.pack(
|
||||||
|
"<B64s",
|
||||||
|
curve_id,
|
||||||
|
pubkey_point,
|
||||||
|
)
|
||||||
|
|
||||||
return hashlib.sha256(binary_format).digest()
|
return hashlib.sha256(binary_format).digest()
|
||||||
|
|
||||||
@@ -1465,7 +1542,7 @@ def main(custom_commandline=None):
|
|||||||
"as per the secure boot version. "
|
"as per the secure boot version. "
|
||||||
"Key file is generated in PEM format, "
|
"Key file is generated in PEM format, "
|
||||||
"Secure Boot V1 - ECDSA NIST256p private key. "
|
"Secure Boot V1 - ECDSA NIST256p private key. "
|
||||||
"Secure Boot V2 - RSA 3072, ECDSA NIST256p, ECDSA NIST192p private key.",
|
"Secure Boot V2 - RSA 3072, ECDSA NIST384p, ECDSA NIST256p, ECDSA NIST192p private key.",
|
||||||
)
|
)
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
"--version",
|
"--version",
|
||||||
@@ -1478,7 +1555,7 @@ def main(custom_commandline=None):
|
|||||||
"--scheme",
|
"--scheme",
|
||||||
"-s",
|
"-s",
|
||||||
help="Scheme of secure boot signing.",
|
help="Scheme of secure boot signing.",
|
||||||
choices=["rsa3072", "ecdsa192", "ecdsa256"],
|
choices=["rsa3072", "ecdsa192", "ecdsa256", "ecdsa384"],
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
@@ -1489,7 +1566,7 @@ def main(custom_commandline=None):
|
|||||||
"sign_data",
|
"sign_data",
|
||||||
help="Sign a data file for use with secure boot. "
|
help="Sign a data file for use with secure boot. "
|
||||||
"Signing algorithm is deterministic ECDSA w/ SHA-512 (V1) "
|
"Signing algorithm is deterministic ECDSA w/ SHA-512 (V1) "
|
||||||
"or either RSA-PSS or ECDSA w/ SHA-256 (V2).",
|
"or either RSA-PSS or ECDSA w/ SHA-256 or ECDSA w/ SHA-384 (V2).",
|
||||||
)
|
)
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
"--version",
|
"--version",
|
||||||
@@ -1509,7 +1586,7 @@ def main(custom_commandline=None):
|
|||||||
"--append_signatures",
|
"--append_signatures",
|
||||||
"-a",
|
"-a",
|
||||||
help="Append signature block(s) to already signed image. "
|
help="Append signature block(s) to already signed image. "
|
||||||
"Valid only for ESP32-S2.",
|
"Not valid for ESP32 and ESP32-C2.",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
)
|
)
|
||||||
p.add_argument(
|
p.add_argument(
|
||||||
|
Reference in New Issue
Block a user