@@ -187,7 +187,15 @@ def tlv_sha_to_sha(tlv):
187187 keys .X25519 : ['256' , '512' ]
188188}
189189
190- def key_and_user_sha_to_alg_and_tlv (key , user_sha ):
190+ ALLOWED_PURE_KEY_SHA = {
191+ keys .Ed25519 : ['512' ]
192+ }
193+
194+ ALLOWED_PURE_SIG_TLVS = [
195+ TLV_VALUES ['ED25519' ]
196+ ]
197+
198+ def key_and_user_sha_to_alg_and_tlv (key , user_sha , is_pure = False ):
191199 """Matches key and user requested sha to sha alogrithm and TLV name.
192200
193201 The returned tuple will contain hash functions and TVL name.
@@ -202,11 +210,17 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha):
202210 # If key is not None, then we have to filter hash to only allowed
203211 allowed = None
204212 try :
205- allowed = ALLOWED_KEY_SHA [type (key )]
213+ if is_pure :
214+ allowed = ALLOWED_PURE_KEY_SHA [type (key )]
215+ else :
216+ allowed = ALLOWED_KEY_SHA [type (key )]
217+
206218 except KeyError :
207219 raise click .UsageError ("Colud not find allowed hash algorithms for {}"
208220 .format (type (key )))
209- if user_sha == 'auto' :
221+
222+ # Pure enforces auto, and user selection is ignored
223+ if user_sha == 'auto' or is_pure :
210224 return USER_SHA_TO_ALG_AND_TLV [allowed [0 ]]
211225
212226 if user_sha in allowed :
@@ -444,12 +458,13 @@ def ecies_hkdf(self, enckey, plainkey):
444458 def create (self , key , public_key_format , enckey , dependencies = None ,
445459 sw_type = None , custom_tlvs = None , compression_tlvs = None ,
446460 compression_type = None , encrypt_keylen = 128 , clear = False ,
447- fixed_sig = None , pub_key = None , vector_to_sign = None , user_sha = 'auto' ):
461+ fixed_sig = None , pub_key = None , vector_to_sign = None ,
462+ user_sha = 'auto' , is_pure = False ):
448463 self .enckey = enckey
449464
450465 # key decides on sha, then pub_key; of both are none default is used
451466 check_key = key if key is not None else pub_key
452- hash_algorithm , hash_tlv = key_and_user_sha_to_alg_and_tlv (check_key , user_sha )
467+ hash_algorithm , hash_tlv = key_and_user_sha_to_alg_and_tlv (check_key , user_sha , is_pure )
453468
454469 # Calculate the hash of the public key
455470 if key is not None :
@@ -584,12 +599,18 @@ def create(self, key, public_key_format, enckey, dependencies=None,
584599 # EC signatures so called Pure algorithm, designated to be run
585600 # over entire message is used with sha of image as message,
586601 # so, for example, in case of ED25519 we have here SHAxxx-ED25519-SHA512.
587- sha = hash_algorithm ()
588- sha .update (self .payload )
589- digest = sha .digest ()
590- message = digest ;
591- tlv .add (hash_tlv , digest )
592- self .image_hash = digest
602+ if not is_pure :
603+ sha = hash_algorithm ()
604+ sha .update (self .payload )
605+ digest = sha .digest ()
606+ message = digest
607+ tlv .add (hash_tlv , digest )
608+ else :
609+ # Note that when Pure signature is used, there is not hash encoded
610+ message = bytes (self .payload )
611+ e = STRUCT_ENDIAN_DICT [self .endian ]
612+ sig_pure = struct .pack (e + '?' , True )
613+ tlv .add ('SIG_PURE' , sig_pure )
593614
594615 if vector_to_sign == 'payload' :
595616 # Stop amending data to the image
@@ -781,7 +802,7 @@ def verify(imgfile, key):
781802 version = struct .unpack ('BBHI' , b [20 :28 ])
782803
783804 if magic != IMAGE_MAGIC :
784- return VerifyResult .INVALID_MAGIC , None , None
805+ return VerifyResult .INVALID_MAGIC , None , None , None
785806
786807 tlv_off = header_size + img_size
787808 tlv_info = b [tlv_off :tlv_off + TLV_INFO_SIZE ]
@@ -792,27 +813,46 @@ def verify(imgfile, key):
792813 magic , tlv_tot = struct .unpack ('HH' , tlv_info )
793814
794815 if magic != TLV_INFO_MAGIC :
795- return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None
816+ return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None , None
817+
818+ # This is set by existence of TLV SIG_PURE
819+ is_pure = False
796820
797821 prot_tlv_size = tlv_off
798822 hash_region = b [:prot_tlv_size ]
823+ tlv_end = tlv_off + tlv_tot
824+ tlv_off += TLV_INFO_SIZE # skip tlv info
825+
826+ # First scan all TLVs in search of SIG_PURE
827+ while tlv_off < tlv_end :
828+ tlv = b [tlv_off :tlv_off + TLV_SIZE ]
829+ tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
830+ if tlv_type == TLV_VALUES ['SIG_PURE' ]:
831+ is_pure = True
832+ break
833+ tlv_off += TLV_SIZE + tlv_len
834+
799835 digest = None
836+ tlv_off = header_size + img_size
800837 tlv_end = tlv_off + tlv_tot
801838 tlv_off += TLV_INFO_SIZE # skip tlv info
802839 while tlv_off < tlv_end :
803840 tlv = b [tlv_off :tlv_off + TLV_SIZE ]
804841 tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
805842 if is_sha_tlv (tlv_type ):
843+ if is_pure :
844+ print ("SHA is not expected for signature over image (pure), ignoring" )
845+ continue
806846 if not tlv_matches_key_type (tlv_type , key ):
807- return VerifyResult .KEY_MISMATCH , None , None
847+ return VerifyResult .KEY_MISMATCH , None , None , None
808848 off = tlv_off + TLV_SIZE
809849 digest = get_digest (tlv_type , hash_region )
810850 if digest == b [off :off + tlv_len ]:
811851 if key is None :
812- return VerifyResult .OK , version , digest
852+ return VerifyResult .OK , version , digest , None
813853 else :
814- return VerifyResult .INVALID_HASH , None , None
815- elif key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
854+ return VerifyResult .INVALID_HASH , None , None , None
855+ elif not is_pure and key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
816856 off = tlv_off + TLV_SIZE
817857 tlv_sig = b [off :off + tlv_len ]
818858 payload = b [:prot_tlv_size ]
@@ -821,9 +861,18 @@ def verify(imgfile, key):
821861 key .verify (tlv_sig , payload )
822862 else :
823863 key .verify_digest (tlv_sig , digest )
824- return VerifyResult .OK , version , digest
864+ return VerifyResult .OK , version , digest , None
865+ except InvalidSignature :
866+ # continue to next TLV
867+ pass
868+ elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS :
869+ off = tlv_off + TLV_SIZE
870+ tlv_sig = b [off :off + tlv_len ]
871+ try :
872+ key .verify_digest (tlv_sig , hash_region )
873+ return VerifyResult .OK , version , None , tlv_sig
825874 except InvalidSignature :
826875 # continue to next TLV
827876 pass
828877 tlv_off += TLV_SIZE + tlv_len
829- return VerifyResult .INVALID_SIGNATURE , None , None
878+ return VerifyResult .INVALID_SIGNATURE , None , None , None
0 commit comments