7272 'ECDSASIG' : 0x22 ,
7373 'RSA3072' : 0x23 ,
7474 'ED25519' : 0x24 ,
75+ 'SIG_PURE' : 0x25 ,
7576 'ENCRSA2048' : 0x30 ,
7677 'ENCKW' : 0x31 ,
7778 'ENCEC256' : 0x32 ,
@@ -174,7 +175,15 @@ def tlv_sha_to_sha(tlv):
174175 keys .X25519 : ['256' , '512' ]
175176}
176177
177- def key_and_user_sha_to_alg_and_tlv (key , user_sha ):
178+ ALLOWED_PURE_KEY_SHA = {
179+ keys .Ed25519 : ['512' ]
180+ }
181+
182+ ALLOWED_PURE_SIG_TLVS = [
183+ TLV_VALUES ['ED25519' ]
184+ ]
185+
186+ def key_and_user_sha_to_alg_and_tlv (key , user_sha , is_pure = False ):
178187 """Matches key and user requested sha to sha alogrithm and TLV name.
179188
180189 The returned tuple will contain hash functions and TVL name.
@@ -189,11 +198,17 @@ def key_and_user_sha_to_alg_and_tlv(key, user_sha):
189198 # If key is not None, then we have to filter hash to only allowed
190199 allowed = None
191200 try :
192- allowed = ALLOWED_KEY_SHA [type (key )]
201+ if is_pure :
202+ allowed = ALLOWED_PURE_KEY_SHA [type (key )]
203+ else :
204+ allowed = ALLOWED_KEY_SHA [type (key )]
205+
193206 except KeyError :
194207 raise click .UsageError ("Colud not find allowed hash algorithms for {}"
195208 .format (type (key )))
196- if user_sha == 'auto' :
209+
210+ # Pure enforces auto, and user selection is ignored
211+ if user_sha == 'auto' or is_pure :
197212 return USER_SHA_TO_ALG_AND_TLV [allowed [0 ]]
198213
199214 if user_sha in allowed :
@@ -408,12 +423,13 @@ def ecies_hkdf(self, enckey, plainkey):
408423
409424 def create (self , key , public_key_format , enckey , dependencies = None ,
410425 sw_type = None , custom_tlvs = None , encrypt_keylen = 128 , clear = False ,
411- fixed_sig = None , pub_key = None , vector_to_sign = None , user_sha = 'auto' ):
426+ fixed_sig = None , pub_key = None , vector_to_sign = None , user_sha = 'auto' ,
427+ is_pure = False ):
412428 self .enckey = enckey
413429
414430 # key decides on sha, then pub_key; of both are none default is used
415431 check_key = key if key is not None else pub_key
416- hash_algorithm , hash_tlv = key_and_user_sha_to_alg_and_tlv (check_key , user_sha )
432+ hash_algorithm , hash_tlv = key_and_user_sha_to_alg_and_tlv (check_key , user_sha , is_pure )
417433
418434 # Calculate the hash of the public key
419435 if key is not None :
@@ -538,11 +554,18 @@ def create(self, key, public_key_format, enckey, dependencies=None,
538554 # EC signatures so called Pure algorithm, designated to be run
539555 # over entire message is used with sha of image as message,
540556 # so, for example, in case of ED25519 we have here SHAxxx-ED25519-SHA512.
541- sha = hash_algorithm ()
542- sha .update (self .payload )
543- digest = sha .digest ()
544- message = digest ;
545- tlv .add (hash_tlv , digest )
557+ if not is_pure :
558+ sha = hash_algorithm ()
559+ sha .update (self .payload )
560+ digest = sha .digest ()
561+ message = digest
562+ tlv .add (hash_tlv , digest )
563+ else :
564+ # Note that when Pure signature is used, there is not hash encoded
565+ message = bytes (self .payload )
566+ e = STRUCT_ENDIAN_DICT [self .endian ]
567+ sig_pure = struct .pack (e + '?' , True )
568+ tlv .add ('SIG_PURE' , sig_pure )
546569
547570 if vector_to_sign == 'payload' :
548571 # Stop amending data to the image
@@ -728,7 +751,7 @@ def verify(imgfile, key):
728751 version = struct .unpack ('BBHI' , b [20 :28 ])
729752
730753 if magic != IMAGE_MAGIC :
731- return VerifyResult .INVALID_MAGIC , None , None
754+ return VerifyResult .INVALID_MAGIC , None , None , None
732755
733756 tlv_off = header_size + img_size
734757 tlv_info = b [tlv_off :tlv_off + TLV_INFO_SIZE ]
@@ -739,27 +762,46 @@ def verify(imgfile, key):
739762 magic , tlv_tot = struct .unpack ('HH' , tlv_info )
740763
741764 if magic != TLV_INFO_MAGIC :
742- return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None
765+ return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None , None
766+
767+ # This is set by existence of TLV SIG_PURE
768+ is_pure = False
743769
744770 prot_tlv_size = tlv_off
745771 hash_region = b [:prot_tlv_size ]
772+ tlv_end = tlv_off + tlv_tot
773+ tlv_off += TLV_INFO_SIZE # skip tlv info
774+
775+ # First scan all TLVs in search of SIG_PURE
776+ while tlv_off < tlv_end :
777+ tlv = b [tlv_off :tlv_off + TLV_SIZE ]
778+ tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
779+ if tlv_type == TLV_VALUES ['SIG_PURE' ]:
780+ is_pure = True
781+ break
782+ tlv_off += TLV_SIZE + tlv_len
783+
746784 digest = None
785+ tlv_off = header_size + img_size
747786 tlv_end = tlv_off + tlv_tot
748787 tlv_off += TLV_INFO_SIZE # skip tlv info
749788 while tlv_off < tlv_end :
750789 tlv = b [tlv_off :tlv_off + TLV_SIZE ]
751790 tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
752791 if is_sha_tlv (tlv_type ):
792+ if is_pure :
793+ print ("SHA is not expected for signature over image (pure), ignoring" )
794+ continue
753795 if not tlv_matches_key_type (tlv_type , key ):
754- return VerifyResult .KEY_MISMATCH , None , None
796+ return VerifyResult .KEY_MISMATCH , None , None , None
755797 off = tlv_off + TLV_SIZE
756798 digest = get_digest (tlv_type , hash_region )
757799 if digest == b [off :off + tlv_len ]:
758800 if key is None :
759- return VerifyResult .OK , version , digest
801+ return VerifyResult .OK , version , digest , None
760802 else :
761- return VerifyResult .INVALID_HASH , None , None
762- elif key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
803+ return VerifyResult .INVALID_HASH , None , None , None
804+ elif not is_pure and key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
763805 off = tlv_off + TLV_SIZE
764806 tlv_sig = b [off :off + tlv_len ]
765807 payload = b [:prot_tlv_size ]
@@ -768,9 +810,18 @@ def verify(imgfile, key):
768810 key .verify (tlv_sig , payload )
769811 else :
770812 key .verify_digest (tlv_sig , digest )
771- return VerifyResult .OK , version , digest
813+ return VerifyResult .OK , version , digest , None
814+ except InvalidSignature :
815+ # continue to next TLV
816+ pass
817+ elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS :
818+ off = tlv_off + TLV_SIZE
819+ tlv_sig = b [off :off + tlv_len ]
820+ try :
821+ key .verify_digest (tlv_sig , hash_region )
822+ return VerifyResult .OK , version , None , tlv_sig
772823 except InvalidSignature :
773824 # continue to next TLV
774825 pass
775826 tlv_off += TLV_SIZE + tlv_len
776- return VerifyResult .INVALID_SIGNATURE , None , None
827+ return VerifyResult .INVALID_SIGNATURE , None , None , None
0 commit comments