72
72
'ECDSASIG' : 0x22 ,
73
73
'RSA3072' : 0x23 ,
74
74
'ED25519' : 0x24 ,
75
+ 'SIG_PURE' : 0x25 ,
75
76
'ENCRSA2048' : 0x30 ,
76
77
'ENCKW' : 0x31 ,
77
78
'ENCEC256' : 0x32 ,
@@ -174,7 +175,15 @@ def tlv_sha_to_sha(tlv):
174
175
keys .X25519 : ['256' , '512' ]
175
176
}
176
177
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 ):
178
187
"""Matches key and user requested sha to sha alogrithm and TLV name.
179
188
180
189
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):
189
198
# If key is not None, then we have to filter hash to only allowed
190
199
allowed = None
191
200
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
+
193
206
except KeyError :
194
207
raise click .UsageError ("Colud not find allowed hash algorithms for {}"
195
208
.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 :
197
212
return USER_SHA_TO_ALG_AND_TLV [allowed [0 ]]
198
213
199
214
if user_sha in allowed :
@@ -408,12 +423,13 @@ def ecies_hkdf(self, enckey, plainkey):
408
423
409
424
def create (self , key , public_key_format , enckey , dependencies = None ,
410
425
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 ):
412
428
self .enckey = enckey
413
429
414
430
# key decides on sha, then pub_key; of both are none default is used
415
431
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 )
417
433
418
434
# Calculate the hash of the public key
419
435
if key is not None :
@@ -538,11 +554,18 @@ def create(self, key, public_key_format, enckey, dependencies=None,
538
554
# EC signatures so called Pure algorithm, designated to be run
539
555
# over entire message is used with sha of image as message,
540
556
# 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 )
546
569
547
570
if vector_to_sign == 'payload' :
548
571
# Stop amending data to the image
@@ -728,7 +751,7 @@ def verify(imgfile, key):
728
751
version = struct .unpack ('BBHI' , b [20 :28 ])
729
752
730
753
if magic != IMAGE_MAGIC :
731
- return VerifyResult .INVALID_MAGIC , None , None
754
+ return VerifyResult .INVALID_MAGIC , None , None , None
732
755
733
756
tlv_off = header_size + img_size
734
757
tlv_info = b [tlv_off :tlv_off + TLV_INFO_SIZE ]
@@ -739,27 +762,46 @@ def verify(imgfile, key):
739
762
magic , tlv_tot = struct .unpack ('HH' , tlv_info )
740
763
741
764
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
743
769
744
770
prot_tlv_size = tlv_off
745
771
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
+
746
784
digest = None
785
+ tlv_off = header_size + img_size
747
786
tlv_end = tlv_off + tlv_tot
748
787
tlv_off += TLV_INFO_SIZE # skip tlv info
749
788
while tlv_off < tlv_end :
750
789
tlv = b [tlv_off :tlv_off + TLV_SIZE ]
751
790
tlv_type , _ , tlv_len = struct .unpack ('BBH' , tlv )
752
791
if is_sha_tlv (tlv_type ):
792
+ if is_pure :
793
+ print ("SHA is not expected for signature over image (pure), ignoring" )
794
+ continue
753
795
if not tlv_matches_key_type (tlv_type , key ):
754
- return VerifyResult .KEY_MISMATCH , None , None
796
+ return VerifyResult .KEY_MISMATCH , None , None , None
755
797
off = tlv_off + TLV_SIZE
756
798
digest = get_digest (tlv_type , hash_region )
757
799
if digest == b [off :off + tlv_len ]:
758
800
if key is None :
759
- return VerifyResult .OK , version , digest
801
+ return VerifyResult .OK , version , digest , None
760
802
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 ()]:
763
805
off = tlv_off + TLV_SIZE
764
806
tlv_sig = b [off :off + tlv_len ]
765
807
payload = b [:prot_tlv_size ]
@@ -768,9 +810,18 @@ def verify(imgfile, key):
768
810
key .verify (tlv_sig , payload )
769
811
else :
770
812
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
772
823
except InvalidSignature :
773
824
# continue to next TLV
774
825
pass
775
826
tlv_off += TLV_SIZE + tlv_len
776
- return VerifyResult .INVALID_SIGNATURE , None , None
827
+ return VerifyResult .INVALID_SIGNATURE , None , None , None
0 commit comments