_CreateHeader() signs twice, once for the image and once for the first header, with the same key and padding. Move the signing into a _sign() helper rather than repeating it.
This is a preparation for signing with an OpenSSL engine, which needs a second implementation of _sign(). Adjust testPreLoadInvalidKey() test to verify that signing is never attempted for a key with the wrong size. Signed-off-by: Lorenz Kofler <[email protected]> --- Changes in v2: - Move the invalid-key test change into this patch to verify that signing is not attempted for a key with the wrong size. tools/binman/etype/pre_load.py | 49 +++++++++++++++++++++------------- tools/binman/ftest.py | 12 ++++++--- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/tools/binman/etype/pre_load.py b/tools/binman/etype/pre_load.py index 0d953cb258e..0cf635ab23a 100644 --- a/tools/binman/etype/pre_load.py +++ b/tools/binman/etype/pre_load.py @@ -86,6 +86,31 @@ def ReadNode(self): if self.key_path is None: self.key_path = '' + def _sign(self, data, key, hash_name, padding_name): + """Sign data with a key + + Args: + data (bytes): Data to sign + key (RsaKey): Key to sign with + hash_name (str): Hash algorithm to use + padding_name (str): Padding to use + + Returns: + bytes: Signature + """ + hash_data = SHAS[hash_name].new() + hash_data.update(data) + + if padding_name == "pss": + salt_len = key.size_in_bytes() - hash_data.digest_size - 2 + padding = pss + padding_args = {'salt_bytes': salt_len} + else: + padding = pkcs1_15 + padding_args = {} + + return padding.new(key, **padding_args).sign(hash_data) + def _CreateHeader(self): """Create a pre load header""" hash_name, sign_name = self.algo_name.split(',') @@ -105,26 +130,13 @@ def _CreateHeader(self): if key.size_in_bytes() != RSAS[sign_name]: self.Raise("The key " + self.key_name + " don't have the expected size") - # Compute the hash - hash_image = SHAS[hash_name].new() - hash_image.update(self.image) - - # Compute the signature if padding_name is None: padding_name = "pkcs-1.5" - padding = None - padding_args = None - if padding_name == "pss": - salt_len = key.size_in_bytes() - hash_image.digest_size - 2 - padding = pss - padding_args = {'salt_bytes': salt_len} - elif padding_name == "pkcs-1.5": - padding = pkcs1_15 - padding_args = {} - else: + if padding_name not in ("pss", "pkcs-1.5"): self.Raise(padding_name + " is not supported") - sig = padding.new(key, **padding_args).sign(hash_image) + # Compute the signature + sig = self._sign(self.image, key, hash_name, padding_name) hash_sig = SHA256.new() hash_sig.update(sig) @@ -142,9 +154,8 @@ def _CreateHeader(self): ofs_img_sig, flags, reserved0, reserved1, hash_sig.digest()) - hash_first_header = SHAS[hash_name].new() - hash_first_header.update(first_header) - sig_first_header = padding.new(key, **padding_args).sign(hash_first_header) + sig_first_header = self._sign(first_header, key, hash_name, + padding_name) data = first_header + sig_first_header + sig pad = bytearray(self.header_size - len(data)) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 2fb452b4e46..4002f6837f4 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -5903,12 +5903,18 @@ def testPreLoadInvalidAlgo(self): def testPreLoadInvalidKey(self): """Test an image with a pre-load header with an invalid key""" + from binman.etype import pre_load + entry_args = { 'pre-load-key-path': os.path.join(self._binman_dir, 'test'), } - with self.assertRaises(ValueError) as e: - data = self._DoReadFileDtb('security/pre_load_invalid_key.dts', - entry_args=entry_args) + with unittest.mock.patch.object( + pre_load.Entry_pre_load, '_sign', + side_effect=AssertionError('signing should not be attempted')): + with self.assertRaisesRegex(ValueError, + "don't have the expected size"): + self._DoReadFileDtb('security/pre_load_invalid_key.dts', + entry_args=entry_args) def testPreLoadEncryptedFit(self): """Test an encrypted FIT image with a pre-load header""" -- 2.55.0
