@@ -188,7 +188,15 @@ def tlv_sha_to_sha(tlv):
188
188
keys .X25519 : ['256' , '512' ]
189
189
}
190
190
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 ):
192
200
"""Matches key and user requested sha to sha alogrithm and TLV name.
193
201
194
202
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):
203
211
# If key is not None, then we have to filter hash to only allowed
204
212
allowed = None
205
213
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
+
207
219
except KeyError :
208
220
raise click .UsageError ("Colud not find allowed hash algorithms for {}"
209
221
.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 :
211
225
return USER_SHA_TO_ALG_AND_TLV [allowed [0 ]]
212
226
213
227
if user_sha in allowed :
@@ -445,12 +459,13 @@ def ecies_hkdf(self, enckey, plainkey):
445
459
def create (self , key , public_key_format , enckey , dependencies = None ,
446
460
sw_type = None , custom_tlvs = None , compression_tlvs = None ,
447
461
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 ):
449
464
self .enckey = enckey
450
465
451
466
# key decides on sha, then pub_key; of both are none default is used
452
467
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 )
454
469
455
470
# Calculate the hash of the public key
456
471
if key is not None :
@@ -590,9 +605,16 @@ def create(self, key, public_key_format, enckey, dependencies=None,
590
605
sha = hash_algorithm ()
591
606
sha .update (self .payload )
592
607
digest = sha .digest ()
593
- message = digest ;
594
608
tlv .add (hash_tlv , digest )
595
- self .image_hash = digest
609
+ # Unless pure, we are signing digest.
610
+ message = digest
611
+
612
+ if is_pure :
613
+ # Note that when Pure signature is used, hash TLV is not present.
614
+ message = bytes (self .payload )
615
+ e = STRUCT_ENDIAN_DICT [self .endian ]
616
+ sig_pure = struct .pack (e + '?' , True )
617
+ tlv .add ('SIG_PURE' , sig_pure )
596
618
597
619
if vector_to_sign == 'payload' :
598
620
# Stop amending data to the image
@@ -784,7 +806,7 @@ def verify(imgfile, key):
784
806
version = struct .unpack ('BBHI' , b [20 :28 ])
785
807
786
808
if magic != IMAGE_MAGIC :
787
- return VerifyResult .INVALID_MAGIC , None , None
809
+ return VerifyResult .INVALID_MAGIC , None , None , None
788
810
789
811
tlv_off = header_size + img_size
790
812
tlv_info = b [tlv_off :tlv_off + TLV_INFO_SIZE ]
@@ -795,27 +817,43 @@ def verify(imgfile, key):
795
817
magic , tlv_tot = struct .unpack ('HH' , tlv_info )
796
818
797
819
if magic != TLV_INFO_MAGIC :
798
- return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None
820
+ return VerifyResult .INVALID_TLV_INFO_MAGIC , None , None , None
821
+
822
+ # This is set by existence of TLV SIG_PURE
823
+ is_pure = False
799
824
800
825
prot_tlv_size = tlv_off
801
826
hash_region = b [:prot_tlv_size ]
827
+ tlv_end = tlv_off + tlv_tot
828
+ tlv_off += TLV_INFO_SIZE # skip tlv info
829
+
830
+ # First scan all TLVs in search of SIG_PURE
831
+ while tlv_off < tlv_end :
832
+ tlv = b [tlv_off :tlv_off + TLV_SIZE ]
833
+ tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
834
+ if tlv_type == TLV_VALUES ['SIG_PURE' ]:
835
+ is_pure = True
836
+ break
837
+ tlv_off += TLV_SIZE + tlv_len
838
+
802
839
digest = None
840
+ tlv_off = header_size + img_size
803
841
tlv_end = tlv_off + tlv_tot
804
842
tlv_off += TLV_INFO_SIZE # skip tlv info
805
843
while tlv_off < tlv_end :
806
844
tlv = b [tlv_off :tlv_off + TLV_SIZE ]
807
845
tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
808
846
if is_sha_tlv (tlv_type ):
809
847
if not tlv_matches_key_type (tlv_type , key ):
810
- return VerifyResult .KEY_MISMATCH , None , None
848
+ return VerifyResult .KEY_MISMATCH , None , None , None
811
849
off = tlv_off + TLV_SIZE
812
850
digest = get_digest (tlv_type , hash_region )
813
851
if digest == b [off :off + tlv_len ]:
814
852
if key is None :
815
- return VerifyResult .OK , version , digest
853
+ return VerifyResult .OK , version , digest , None
816
854
else :
817
- return VerifyResult .INVALID_HASH , None , None
818
- elif key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
855
+ return VerifyResult .INVALID_HASH , None , None , None
856
+ elif not is_pure and key is not None and tlv_type == TLV_VALUES [key .sig_tlv ()]:
819
857
off = tlv_off + TLV_SIZE
820
858
tlv_sig = b [off :off + tlv_len ]
821
859
payload = b [:prot_tlv_size ]
@@ -824,9 +862,18 @@ def verify(imgfile, key):
824
862
key .verify (tlv_sig , payload )
825
863
else :
826
864
key .verify_digest (tlv_sig , digest )
827
- return VerifyResult .OK , version , digest
865
+ return VerifyResult .OK , version , digest , None
866
+ except InvalidSignature :
867
+ # continue to next TLV
868
+ pass
869
+ elif is_pure and key is not None and tlv_type in ALLOWED_PURE_SIG_TLVS :
870
+ off = tlv_off + TLV_SIZE
871
+ tlv_sig = b [off :off + tlv_len ]
872
+ try :
873
+ key .verify_digest (tlv_sig , hash_region )
874
+ return VerifyResult .OK , version , None , tlv_sig
828
875
except InvalidSignature :
829
876
# continue to next TLV
830
877
pass
831
878
tlv_off += TLV_SIZE + tlv_len
832
- return VerifyResult .INVALID_SIGNATURE , None , None
879
+ return VerifyResult .INVALID_SIGNATURE , None , None , None
0 commit comments