2020import base64
2121import getpass
2222import lzma
23+ import os
2324import re
2425import struct
2526import sys
@@ -324,6 +325,14 @@ def create_lzma2_header(dictsize, pb, lc, lp):
324325 header .append ( ( pb * 5 + lp ) * 9 + lc )
325326 return header
326327
328+ def match_sig_enc_key (skey , ekey ):
329+ ok = ((isinstance (skey , keys .ECDSA256P1 ) and isinstance (ekey , keys .ECDSA256P1Public )) or
330+ (isinstance (skey , keys .ECDSA384P1 ) and isinstance (ekey , keys .ECDSA384P1Public )) or
331+ (isinstance (skey , keys .RSA ) and isinstance (ekey , keys .RSAPublic ))
332+ )
333+
334+ return ok
335+
327336class BasedIntParamType (click .ParamType ):
328337 name = 'integer'
329338
@@ -454,13 +463,17 @@ def convert(self, value, param, ctx):
454463 help = 'Unique image class identifier, format: (<raw_uuid>|<image_class_name>)' )
455464@click .option ('--manifest' , default = None , required = False ,
456465 help = 'Path to the update manifest file' )
457- def sign (key , public_key_format , align , version , pad_sig , header_size ,
466+ @click .option ('--aes-key' , default = None , required = False ,
467+ help = 'String representing raw AES key, format: hex byte string of 32 or 64'
468+ 'hexadecimal characters' )
469+ @click .pass_context
470+ def sign (ctx , key , public_key_format , align , version , pad_sig , header_size ,
458471 pad_header , slot_size , pad , confirm , test , max_sectors , overwrite_only ,
459472 endian , encrypt_keylen , encrypt , compression , infile , outfile ,
460473 dependencies , load_addr , hex_addr , erased_val , save_enctlv ,
461474 security_counter , boot_record , custom_tlv , rom_fixed , max_align ,
462475 clear , fix_sig , fix_sig_pubkey , sig_out , user_sha , hmac_sha , is_pure ,
463- vector_to_sign , non_bootable , vid , cid , manifest ):
476+ vector_to_sign , non_bootable , vid , cid , manifest , aes_key ):
464477
465478 if confirm or test :
466479 # Confirmed but non-padded images don't make much sense, because
@@ -477,17 +490,23 @@ def sign(key, public_key_format, align, version, pad_sig, header_size,
477490 manifest = manifest )
478491 compression_tlvs = {}
479492 img .load (infile )
493+
480494 key = load_key (key ) if key else None
481- enckey = load_key (encrypt ) if encrypt else None
482- if enckey and key and ((isinstance (key , keys .ECDSA256P1 ) and
483- not isinstance (enckey , keys .ECDSA256P1Public ))
484- or (isinstance (key , keys .ECDSA384P1 ) and
485- not isinstance (enckey , keys .ECDSA384P1Public ))
486- or (isinstance (key , keys .RSA ) and
487- not isinstance (enckey , keys .RSAPublic ))):
488- # FIXME
489- raise click .UsageError ("Signing and encryption must use the same "
490- "type of key" )
495+ enckey = None
496+ if not aes_key :
497+ enckey = load_key (encrypt ) if encrypt else None
498+ if enckey and not match_sig_enc_key (key , enckey ):
499+ # FIXME
500+ raise click .UsageError ("Signing and encryption must use the same "
501+ "type of key" )
502+ else :
503+ if encrypt :
504+ encrypt = None
505+ print ('Raw AES key overrides --key, there will be no encrypted key added to the image' )
506+ if clear :
507+ print ('--clear overrides raw AES key, image will not be encrypted' )
508+ if ctx .get_parameter_source ('encrypt_keylen' ) != click .core .ParameterSource .DEFAULT :
509+ print ('Raw AES key len overrides --encrypt-keylen' )
491510
492511 if pad_sig and hasattr (key , 'pad_sig' ):
493512 key .pad_sig = True
@@ -532,9 +551,26 @@ def sign(key, public_key_format, align, version, pad_sig, header_size,
532551 'Pure signatures, currently, enforces preferred hash algorithm, '
533552 'and forbids sha selection by user.' )
534553
554+ plainkey = None
555+ if aes_key :
556+ # Converting the command line provided raw AES key to byte array;
557+ # this aray will be truncated to desired len.
558+ plainkey = bytes .fromhex (aes_key )
559+ plainkey_len = len (plainkey )
560+ if plainkey_len not in (16 , 32 ):
561+ raise click .UsageError ("Provided keylen, {int(plainkey_len)} in bytes, not supported" )
562+ elif enckey :
563+ if encrypt_keylen == 256 :
564+ encrypt_keylen_bytes = 32
565+ else :
566+ encrypt_keylen_bytes = 16
567+
568+ # No AES plain key and there is request to encrypt, generate random AES key
569+ plainkey = os .urandom (encrypt_keylen_bytes )
570+
535571 if compression in ["lzma2" , "lzma2armthumb" ]:
536572 img .create (key , public_key_format , enckey , dependencies , boot_record ,
537- custom_tlvs , compression_tlvs , None , int ( encrypt_keylen ) , clear ,
573+ custom_tlvs , compression_tlvs , None , None , clear ,
538574 baked_signature , pub_key , vector_to_sign , user_sha = user_sha ,
539575 hmac_sha = hmac_sha , is_pure = is_pure , keep_comp_size = False , dont_encrypt = True )
540576 compressed_img = image .Image (version = decode_version (version ),
@@ -580,13 +616,13 @@ def sign(key, public_key_format, align, version, pad_sig, header_size,
580616 keep_comp_size = True
581617 compressed_img .create (key , public_key_format , enckey ,
582618 dependencies , boot_record , custom_tlvs , compression_tlvs ,
583- compression , int ( encrypt_keylen ) , clear , baked_signature ,
619+ compression , plainkey , clear , baked_signature ,
584620 pub_key , vector_to_sign , user_sha = user_sha , hmac_sha = hmac_sha ,
585621 is_pure = is_pure , keep_comp_size = keep_comp_size )
586622 img = compressed_img
587623 else :
588624 img .create (key , public_key_format , enckey , dependencies , boot_record ,
589- custom_tlvs , compression_tlvs , None , int ( encrypt_keylen ) , clear ,
625+ custom_tlvs , compression_tlvs , None , plainkey , clear ,
590626 baked_signature , pub_key , vector_to_sign , user_sha = user_sha ,
591627 hmac_sha = hmac_sha , is_pure = is_pure )
592628 img .save (outfile , hex_addr )
0 commit comments