@@ -188,7 +188,15 @@ def tlv_sha_to_sha(tlv):
188188 keys .X25519 : ['256' , '512' ]
189189}
190190
191- def key_and_user_sha_to_alg_and_tlv (key , user_sha ):
191+ ALLOWED_PURE_KEY_SHA = {
192+ keys .Ed25519 : ['512' ]
193+ }
194+
195+ ALLOWED_PURE_SIG_TLVS = [
196+ TLV_VALUES ['ED25519' ]
197+ ]
198+
199+ def key_and_user_sha_to_alg_and_tlv (key , user_sha , is_pure = False ):
192200 """Matches key and user requested sha to sha alogrithm and TLV name.
193201
194202 The returned tuple will contain hash functions and TVL name.
@@ -203,11 +211,17 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha):
203211 # If key is not None, then we have to filter hash to only allowed
204212 allowed = None
205213 try :
206- allowed = ALLOWED_KEY_SHA [type (key )]
214+ if is_pure :
215+ allowed = ALLOWED_PURE_KEY_SHA [type (key )]
216+ else :
217+ allowed = ALLOWED_KEY_SHA [type (key )]
218+
207219 except KeyError :
208220 raise click .UsageError ("Colud not find allowed hash algorithms for {}"
209221 .format (type (key )))
210- if user_sha == 'auto' :
222+
223+ # Pure enforces auto, and user selection is ignored
224+ if user_sha == 'auto' or is_pure :
211225 return USER_SHA_TO_ALG_AND_TLV [allowed [0 ]]
212226
213227 if user_sha in allowed :
@@ -445,12 +459,13 @@ def ecies_hkdf(self, enckey, plainkey):
445459 def create (self , key , public_key_format , enckey , dependencies = None ,
446460 sw_type = None , custom_tlvs = None , compression_tlvs = None ,
447461 compression_type = None , encrypt_keylen = 128 , clear = False ,
448- fixed_sig = None , pub_key = None , vector_to_sign = None , user_sha = 'auto' ):
462+ fixed_sig = None , pub_key = None , vector_to_sign = None ,
463+ user_sha = 'auto' , is_pure = False ):
449464 self .enckey = enckey
450465
451466 # key decides on sha, then pub_key; of both are none default is used
452467 check_key = key if key is not None else pub_key
453- hash_algorithm , hash_tlv = key_and_user_sha_to_alg_and_tlv (check_key , user_sha )
468+ hash_algorithm , hash_tlv = key_and_user_sha_to_alg_and_tlv (check_key , user_sha , is_pure )
454469
455470 # Calculate the hash of the public key
456471 if key is not None :
@@ -587,12 +602,18 @@ def create(self, key, public_key_format, enckey, dependencies=None,
587602 # EC signatures so called Pure algorithm, designated to be run
588603 # over entire message is used with sha of image as message,
589604 # so, for example, in case of ED25519 we have here SHAxxx-ED25519-SHA512.
590- sha = hash_algorithm ()
591- sha .update (self .payload )
592- digest = sha .digest ()
593- message = digest ;
594- tlv .add (hash_tlv , digest )
595- self .image_hash = digest
605+ if not is_pure :
606+ sha = hash_algorithm ()
607+ sha .update (self .payload )
608+ digest = sha .digest ()
609+ message = digest
610+ tlv .add (hash_tlv , digest )
611+ else :
612+ # Note that when Pure signature is used, hash TLV is not present.
613+ message = bytes (self .payload )
614+ e = STRUCT_ENDIAN_DICT [self .endian ]
615+ sig_pure = struct .pack (e + '?' , True )
616+ tlv .add ('SIG_PURE' , sig_pure )
596617
597618 if vector_to_sign == 'payload' :
598619 # Stop amending data to the image
@@ -784,7 +805,7 @@ def verify(imgfile, key):
784805 version = struct .unpack ('BBHI' , b [20 :28 ])
785806
786807 if magic != IMAGE_MAGIC :
787- return VerifyResult .INVALID_MAGIC , None , None
808+ return VerifyResult .INVALID_MAGIC , None , None , None
788809
789810 tlv_off = header_size + img_size
790811 tlv_info = b [tlv_off :tlv_off + TLV_INFO_SIZE ]
@@ -795,27 +816,46 @@ def verify(imgfile, key):
795816 magic , tlv_tot = struct .unpack ('HH' , tlv_info )
796817
797818 if magic != TLV_INFO_MAGIC :
798- return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None
819+ return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None , None
820+
821+ # This is set by existence of TLV SIG_PURE
822+ is_pure = False
799823
800824 prot_tlv_size = tlv_off
801825 hash_region = b [:prot_tlv_size ]
826+ tlv_end = tlv_off + tlv_tot
827+ tlv_off += TLV_INFO_SIZE # skip tlv info
828+
829+ # First scan all TLVs in search of SIG_PURE
830+ while tlv_off < tlv_end :
831+ tlv = b [tlv_off :tlv_off + TLV_SIZE ]
832+ tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
833+ if tlv_type == TLV_VALUES ['SIG_PURE' ]:
834+ is_pure = True
835+ break
836+ tlv_off += TLV_SIZE + tlv_len
837+
802838 digest = None
839+ tlv_off = header_size + img_size
803840 tlv_end = tlv_off + tlv_tot
804841 tlv_off += TLV_INFO_SIZE # skip tlv info
805842 while tlv_off < tlv_end :
806843 tlv = b [tlv_off :tlv_off + TLV_SIZE ]
807844 tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
808845 if is_sha_tlv (tlv_type ):
846+ if is_pure :
847+ print ("SHA is not expected for signature over image (pure), ignoring" )
848+ continue
809849 if not tlv_matches_key_type (tlv_type , key ):
810- return VerifyResult .KEY_MISMATCH , None , None
850+ return VerifyResult .KEY_MISMATCH , None , None , None
811851 off = tlv_off + TLV_SIZE
812852 digest = get_digest (tlv_type , hash_region )
813853 if digest == b [off :off + tlv_len ]:
814854 if key is None :
815- return VerifyResult .OK , version , digest
855+ return VerifyResult .OK , version , digest , None
816856 else :
817- return VerifyResult .INVALID_HASH , None , None
818- elif key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
857+ return VerifyResult .INVALID_HASH , None , None , None
858+ elif not is_pure and key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
819859 off = tlv_off + TLV_SIZE
820860 tlv_sig = b [off :off + tlv_len ]
821861 payload = b [:prot_tlv_size ]
@@ -824,9 +864,18 @@ def verify(imgfile, key):
824864 key .verify (tlv_sig , payload )
825865 else :
826866 key .verify_digest (tlv_sig , digest )
827- return VerifyResult .OK , version , digest
867+ return VerifyResult .OK , version , digest , None
868+ except InvalidSignature :
869+ # continue to next TLV
870+ pass
871+ elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS :
872+ off = tlv_off + TLV_SIZE
873+ tlv_sig = b [off :off + tlv_len ]
874+ try :
875+ key .verify_digest (tlv_sig , hash_region )
876+ return VerifyResult .OK , version , None , tlv_sig
828877 except InvalidSignature :
829878 # continue to next TLV
830879 pass
831880 tlv_off += TLV_SIZE + tlv_len
832- return VerifyResult .INVALID_SIGNATURE , None , None
881+ return VerifyResult .INVALID_SIGNATURE , None , None , None
0 commit comments