Skip to content

Commit 36f8bf3

Browse files
rustammendeldavidvincze
authored andcommitted
imgtool: Fix verify command for edcsa-p384 signed images
Fixed hash algorithm defaults to SHA256 in case no key provided. Verification improved by adding check for key - tlv mismatch, VerifyResult.KEY_MISMATCH added to indicate this case. Multiple styling fixes and import optimisation, exception handling. Signed-off-by: Rustam Ismayilov <[email protected]> Change-Id: I61a588de5b39678707c0179f4edaa411ceb67c8e
1 parent 2712f74 commit 36f8bf3

File tree

2 files changed

+58
-45
lines changed

2 files changed

+58
-45
lines changed

scripts/imgtool/image.py

Lines changed: 56 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Copyright 2018 Nordic Semiconductor ASA
22
# Copyright 2017-2020 Linaro Limited
3-
# Copyright 2019-2023 Arm Limited
3+
# Copyright 2019-2024 Arm Limited
44
#
55
# SPDX-License-Identifier: Apache-2.0
66
#
@@ -20,23 +20,25 @@
2020
Image signing and management.
2121
"""
2222

23-
from . import version as versmod
24-
from .boot_record import create_sw_component_data
25-
import click
26-
from enum import Enum
27-
from intelhex import IntelHex
2823
import hashlib
29-
import struct
3024
import os.path
31-
from .keys import rsa, ecdsa, x25519
25+
import struct
26+
from enum import Enum
27+
28+
import click
29+
from cryptography.exceptions import InvalidSignature
30+
from cryptography.hazmat.backends import default_backend
31+
from cryptography.hazmat.primitives import hashes, hmac
3232
from cryptography.hazmat.primitives.asymmetric import ec, padding
3333
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
3434
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
3535
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
3636
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
37-
from cryptography.hazmat.backends import default_backend
38-
from cryptography.hazmat.primitives import hashes, hmac
39-
from cryptography.exceptions import InvalidSignature
37+
from intelhex import IntelHex
38+
39+
from . import version as versmod, keys
40+
from .boot_record import create_sw_component_data
41+
from .keys import rsa, ecdsa, x25519
4042

4143
IMAGE_MAGIC = 0x96f3b83d
4244
IMAGE_HEADER_SIZE = 32
@@ -90,10 +92,8 @@
9092
}
9193

9294
VerifyResult = Enum('VerifyResult',
93-
"""
94-
OK INVALID_MAGIC INVALID_TLV_INFO_MAGIC INVALID_HASH
95-
INVALID_SIGNATURE
96-
""")
95+
['OK', 'INVALID_MAGIC', 'INVALID_TLV_INFO_MAGIC', 'INVALID_HASH', 'INVALID_SIGNATURE',
96+
'KEY_MISMATCH'])
9797

9898

9999
def align_up(num, align):
@@ -135,7 +135,24 @@ def get(self):
135135
return header + bytes(self.buf)
136136

137137

138-
class Image():
138+
def get_digest(tlv_type, hash_region):
139+
if tlv_type == TLV_VALUES["SHA384"]:
140+
sha = hashlib.sha384()
141+
elif tlv_type == TLV_VALUES["SHA256"]:
142+
sha = hashlib.sha256()
143+
144+
sha.update(hash_region)
145+
return sha.digest()
146+
147+
148+
def tlv_matches_key_type(tlv_type, key):
149+
"""Check if provided key matches to TLV record in the image"""
150+
return (key is None or
151+
type(key) == keys.ECDSA384P1 and tlv_type == TLV_VALUES["SHA384"] or
152+
type(key) != keys.ECDSA384P1 and tlv_type == TLV_VALUES["SHA256"])
153+
154+
155+
class Image:
139156

140157
def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE,
141158
pad_header=False, pad=False, confirm=False, align=1,
@@ -178,9 +195,9 @@ def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE,
178195
msb = (self.max_align & 0xff00) >> 8
179196
align = bytes([msb, lsb]) if self.endian == "big" else bytes([lsb, msb])
180197
self.boot_magic = align + bytes([0x2d, 0xe1,
181-
0x5d, 0x29, 0x41, 0x0b,
182-
0x8d, 0x77, 0x67, 0x9c,
183-
0x11, 0x0f, 0x1f, 0x8a, ])
198+
0x5d, 0x29, 0x41, 0x0b,
199+
0x8d, 0x77, 0x67, 0x9c,
200+
0x11, 0x0f, 0x1f, 0x8a, ])
184201

185202
if security_counter == 'auto':
186203
# Security counter has not been explicitly provided,
@@ -321,9 +338,8 @@ def create(self, key, public_key_format, enckey, dependencies=None,
321338
self.enckey = enckey
322339

323340
# Check what hashing algorithm should be used
324-
if (key is not None and isinstance(key, ecdsa.ECDSA384P1) or
325-
pub_key is not None and isinstance(pub_key,
326-
ecdsa.ECDSA384P1Public)):
341+
if (key and isinstance(key, ecdsa.ECDSA384P1)
342+
or pub_key and isinstance(pub_key, ecdsa.ECDSA384P1Public)):
327343
hash_algorithm = hashlib.sha384
328344
hash_tlv = "SHA384"
329345
else:
@@ -430,13 +446,13 @@ def create(self, key, public_key_format, enckey, dependencies=None,
430446
if dependencies is not None:
431447
for i in range(dependencies_num):
432448
payload = struct.pack(
433-
e + 'B3x'+'BBHI',
434-
int(dependencies[DEP_IMAGES_KEY][i]),
435-
dependencies[DEP_VERSIONS_KEY][i].major,
436-
dependencies[DEP_VERSIONS_KEY][i].minor,
437-
dependencies[DEP_VERSIONS_KEY][i].revision,
438-
dependencies[DEP_VERSIONS_KEY][i].build
439-
)
449+
e + 'B3x' + 'BBHI',
450+
int(dependencies[DEP_IMAGES_KEY][i]),
451+
dependencies[DEP_VERSIONS_KEY][i].major,
452+
dependencies[DEP_VERSIONS_KEY][i].minor,
453+
dependencies[DEP_VERSIONS_KEY][i].revision,
454+
dependencies[DEP_VERSIONS_KEY][i].build
455+
)
440456
prot_tlv.add('DEPENDENCY', payload)
441457

442458
if custom_tlvs is not None:
@@ -640,42 +656,37 @@ def verify(imgfile, key):
640656
return VerifyResult.INVALID_MAGIC, None, None
641657

642658
tlv_off = header_size + img_size
643-
tlv_info = b[tlv_off:tlv_off+TLV_INFO_SIZE]
659+
tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE]
644660
magic, tlv_tot = struct.unpack('HH', tlv_info)
645661
if magic == TLV_PROT_INFO_MAGIC:
646662
tlv_off += tlv_tot
647-
tlv_info = b[tlv_off:tlv_off+TLV_INFO_SIZE]
663+
tlv_info = b[tlv_off:tlv_off + TLV_INFO_SIZE]
648664
magic, tlv_tot = struct.unpack('HH', tlv_info)
649665

650666
if magic != TLV_INFO_MAGIC:
651667
return VerifyResult.INVALID_TLV_INFO_MAGIC, None, None
652668

653-
if isinstance(key, ecdsa.ECDSA384P1Public):
654-
sha = hashlib.sha384()
655-
hash_tlv = "SHA384"
656-
else:
657-
sha = hashlib.sha256()
658-
hash_tlv = "SHA256"
659-
660669
prot_tlv_size = tlv_off
661-
sha.update(b[:prot_tlv_size])
662-
digest = sha.digest()
663-
670+
hash_region = b[:prot_tlv_size]
671+
digest = None
664672
tlv_end = tlv_off + tlv_tot
665673
tlv_off += TLV_INFO_SIZE # skip tlv info
666674
while tlv_off < tlv_end:
667-
tlv = b[tlv_off:tlv_off+TLV_SIZE]
675+
tlv = b[tlv_off:tlv_off + TLV_SIZE]
668676
tlv_type, _, tlv_len = struct.unpack('BBH', tlv)
669-
if tlv_type == TLV_VALUES[hash_tlv]:
677+
if tlv_type == TLV_VALUES["SHA256"] or tlv_type == TLV_VALUES["SHA384"]:
678+
if not tlv_matches_key_type(tlv_type, key):
679+
return VerifyResult.KEY_MISMATCH, None, None
670680
off = tlv_off + TLV_SIZE
671-
if digest == b[off:off+tlv_len]:
681+
digest = get_digest(tlv_type, hash_region)
682+
if digest == b[off:off + tlv_len]:
672683
if key is None:
673684
return VerifyResult.OK, version, digest
674685
else:
675686
return VerifyResult.INVALID_HASH, None, None
676687
elif key is not None and tlv_type == TLV_VALUES[key.sig_tlv()]:
677688
off = tlv_off + TLV_SIZE
678-
tlv_sig = b[off:off+tlv_len]
689+
tlv_sig = b[off:off + tlv_len]
679690
payload = b[:prot_tlv_size]
680691
try:
681692
if hasattr(key, 'verify'):

scripts/imgtool/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ def verify(key, imgfile):
228228
print("Image has an invalid hash")
229229
elif ret == image.VerifyResult.INVALID_SIGNATURE:
230230
print("No signature found for the given key")
231+
elif ret == image.VerifyResult.KEY_MISMATCH:
232+
print("Key type does not match TLV record")
231233
else:
232234
print("Unknown return code: {}".format(ret))
233235
sys.exit(1)

0 commit comments

Comments
 (0)