2020import base64
2121import getpass
2222import lzma
23+ import os
2324import re
2425import struct
2526import sys
@@ -322,6 +323,14 @@ def create_lzma2_header(dictsize, pb, lc, lp):
322323 header .append ( ( pb * 5 + lp ) * 9 + lc )
323324 return header
324325
326+ def match_sig_enc_key (skey , ekey ):
327+ ok = ((isinstance (skey , keys .ECDSA256P1 ) and isinstance (ekey , keys .ECDSA256P1Public )) or
328+ (isinstance (skey , keys .ECDSA384P1 ) and isinstance (ekey , keys .ECDSA384P1Public )) or
329+ (isinstance (skey , keys .RSA ) and isinstance (ekey , keys .RSAPublic ))
330+ )
331+
332+ return ok
333+
325334class BasedIntParamType (click .ParamType ):
326335 name = 'integer'
327336
@@ -450,13 +459,17 @@ def convert(self, value, param, ctx):
450459 help = 'Unique vendor identifier, format: (<raw_uuid>|<domain_name)>' )
451460@click .option ('--cid' , default = None , required = False ,
452461 help = 'Unique image class identifier, format: (<raw_uuid>|<image_class_name>)' )
453- def sign (key , public_key_format , align , version , pad_sig , header_size ,
462+ @click .option ('--aes-key' , default = None , required = False ,
463+ help = 'String representing raw AES key, format: hex byte string of 32 or 64'
464+ 'hexadecimal characters' )
465+ @click .pass_context
466+ def sign (ctx , key , public_key_format , align , version , pad_sig , header_size ,
454467 pad_header , slot_size , pad , confirm , test , max_sectors , overwrite_only ,
455468 endian , encrypt_keylen , encrypt , compression , infile , outfile ,
456469 dependencies , load_addr , hex_addr , erased_val , save_enctlv ,
457470 security_counter , boot_record , custom_tlv , rom_fixed , max_align ,
458471 clear , fix_sig , fix_sig_pubkey , sig_out , user_sha , hmac_sha , is_pure ,
459- vector_to_sign , non_bootable , vid , cid ):
472+ vector_to_sign , non_bootable , vid , cid , aes_key ):
460473
461474 if confirm or test :
462475 # Confirmed but non-padded images don't make much sense, because
@@ -472,17 +485,24 @@ def sign(key, public_key_format, align, version, pad_sig, header_size,
472485 non_bootable = non_bootable , vid = vid , cid = cid )
473486 compression_tlvs = {}
474487 img .load (infile )
488+
475489 key = load_key (key ) if key else None
476- enckey = load_key (encrypt ) if encrypt else None
477- if enckey and key and ((isinstance (key , keys .ECDSA256P1 ) and
478- not isinstance (enckey , keys .ECDSA256P1Public ))
479- or (isinstance (key , keys .ECDSA384P1 ) and
480- not isinstance (enckey , keys .ECDSA384P1Public ))
481- or (isinstance (key , keys .RSA ) and
482- not isinstance (enckey , keys .RSAPublic ))):
483- # FIXME
484- raise click .UsageError ("Signing and encryption must use the same "
485- "type of key" )
490+ enckey = None
491+ if not aes_key :
492+ enckey = load_key (encrypt ) if encrypt else None
493+ if enckey and not match_sig_enc_key (key , enckey ):
494+ # FIXME
495+ raise click .UsageError ("Signing and encryption must use the same "
496+ "type of key" )
497+ else :
498+ if encrypt :
499+ encrypt = None
500+ print ('Raw AES key overrides --key, there will be no encrypted key added to the image' )
501+ if clear :
502+ clear = False
503+ print ('Raw AES key overrides --clear, image will be encrypted' )
504+ if ctx .get_parameter_source ('encrypt_keylen' ) != click .core .ParameterSource .DEFAULT :
505+ print ('Raw AES key len overrides --encrypt-keylen' )
486506
487507 if pad_sig and hasattr (key , 'pad_sig' ):
488508 key .pad_sig = True
@@ -527,9 +547,26 @@ def sign(key, public_key_format, align, version, pad_sig, header_size,
527547 'Pure signatures, currently, enforces preferred hash algorithm, '
528548 'and forbids sha selection by user.' )
529549
550+ plainkey = None
551+ if aes_key :
552+ # Converting the command line provided raw AES key to byte array;
553+ # this aray will be truncated to desired len.
554+ plainkey = bytes .fromhex (aes_key )
555+ plainkey_len = len (plainkey )
556+ if plainkey_len not in (16 , 32 ):
557+ raise click .UsageError ("Provided keylen, {int(plainkey_len)} in bytes, not supported" )
558+ elif enckey :
559+ if encrypt_keylen == 256 :
560+ encrypt_keylen_bytes = 32
561+ else :
562+ encrypt_keylen_bytes = 16
563+
564+ # No AES plain key and there is request to encrypt, generate random AES key
565+ plainkey = os .urandom (encrypt_keylen_bytes )
566+
530567 if compression in ["lzma2" , "lzma2armthumb" ]:
531568 img .create (key , public_key_format , enckey , dependencies , boot_record ,
532- custom_tlvs , compression_tlvs , None , int ( encrypt_keylen ) , clear ,
569+ custom_tlvs , compression_tlvs , None , None , clear ,
533570 baked_signature , pub_key , vector_to_sign , user_sha = user_sha ,
534571 hmac_sha = hmac_sha , is_pure = is_pure , keep_comp_size = False , dont_encrypt = True )
535572 compressed_img = image .Image (version = decode_version (version ),
@@ -575,13 +612,13 @@ def sign(key, public_key_format, align, version, pad_sig, header_size,
575612 keep_comp_size = True
576613 compressed_img .create (key , public_key_format , enckey ,
577614 dependencies , boot_record , custom_tlvs , compression_tlvs ,
578- compression , int ( encrypt_keylen ) , clear , baked_signature ,
615+ compression , plainkey , clear , baked_signature ,
579616 pub_key , vector_to_sign , user_sha = user_sha , hmac_sha = hmac_sha ,
580617 is_pure = is_pure , keep_comp_size = keep_comp_size )
581618 img = compressed_img
582619 else :
583620 img .create (key , public_key_format , enckey , dependencies , boot_record ,
584- custom_tlvs , compression_tlvs , None , int ( encrypt_keylen ) , clear ,
621+ custom_tlvs , compression_tlvs , None , plainkey , clear ,
585622 baked_signature , pub_key , vector_to_sign , user_sha = user_sha ,
586623 hmac_sha = hmac_sha , is_pure = is_pure )
587624 img .save (outfile , hex_addr )
0 commit comments