def test_Sign(self): payload_signer = PayloadSigner() input_file = os.path.join(self.testdata_dir, self.SIGFILE) signed_file = payload_signer.Sign(input_file) verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE) self._assertFilesEqual(verify_file, signed_file)
def test_Sign_withExternalSigner_script(self): """Uses testdata/payload_signer.sh as the external payload signer.""" common.OPTIONS.payload_signer = os.path.join( self.testdata_dir, 'payload_signer.sh') common.OPTIONS.payload_signer_args = [ os.path.join(self.testdata_dir, 'testkey.pk8')] payload_signer = PayloadSigner() input_file = os.path.join(self.testdata_dir, self.SIGFILE) signed_file = payload_signer.Sign(input_file) verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE) self._assertFilesEqual(verify_file, signed_file)
def test_Sign_withExternalSigner_openssl(self): """Uses openssl as the external payload signer.""" common.OPTIONS.payload_signer = 'openssl' common.OPTIONS.payload_signer_args = [ 'pkeyutl', '-sign', '-keyform', 'DER', '-inkey', os.path.join(self.testdata_dir, 'testkey.pk8'), '-pkeyopt', 'digest:sha256'] payload_signer = PayloadSigner() input_file = os.path.join(self.testdata_dir, self.SIGFILE) signed_file = payload_signer.Sign(input_file) verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE) self._assertFilesEqual(verify_file, signed_file)
def construct_zip_package_withValidPayload(with_metadata=False): # Cannot use construct_zip_package() since we need a "valid" payload.bin. target_file = construct_target_files() payload = Payload() payload.Generate(target_file) payload_signer = PayloadSigner() payload.Sign(payload_signer) zip_file = common.MakeTempFile(suffix='.zip') with zipfile.ZipFile(zip_file, 'w') as zip_fp: # 'payload.bin', payload.WriteToZip(zip_fp) # Other entries. entries = ['care_map.txt', 'compatibility.zip'] # Put META-INF/com/android/metadata if needed. if with_metadata: entries.append('META-INF/com/android/metadata') for entry in entries: zip_fp.writestr( entry, entry.replace('.', '-').upper(), zipfile.ZIP_STORED) return zip_file
def test_Sign_withDataWipe(self): common.OPTIONS.wipe_user_data = True payload = self._create_payload_full() payload.Sign(PayloadSigner()) with open(payload.payload_properties) as properties_fp: self.assertIn("POWERWASH=1", properties_fp.read())
def test_init_withExternalSigner(self): common.OPTIONS.payload_signer = 'abc' common.OPTIONS.payload_signer_args = ['arg1', 'arg2'] common.OPTIONS.payload_signer_maximum_signature_size = '512' payload_signer = PayloadSigner() self.assertEqual('abc', payload_signer.signer) self.assertEqual(['arg1', 'arg2'], payload_signer.signer_args) self.assertEqual(512, payload_signer.maximum_signature_size)
def test_init_withPassword(self): common.OPTIONS.package_key = os.path.join( self.testdata_dir, 'testkey_with_passwd') common.OPTIONS.key_passwords = { common.OPTIONS.package_key : 'foo', } payload_signer = PayloadSigner() self.assertEqual('openssl', payload_signer.signer)
def test_GetPayloadMetadataOffsetAndSize(self): target_file = construct_target_files() payload = Payload() payload.Generate(target_file) payload_signer = PayloadSigner() payload.Sign(payload_signer) output_file = common.MakeTempFile(suffix='.zip') with zipfile.ZipFile(output_file, 'w') as output_zip: payload.WriteToZip(output_zip) # Find out the payload metadata offset and size. property_files = AbOtaPropertyFiles() with zipfile.ZipFile(output_file) as input_zip: # pylint: disable=protected-access payload_offset, metadata_total = ( property_files._GetPayloadMetadataOffsetAndSize(input_zip)) # Read in the metadata signature directly. with open(output_file, 'rb') as verify_fp: verify_fp.seek(payload_offset + metadata_total - self.SIGNATURE_SIZE) metadata_signature = verify_fp.read(self.SIGNATURE_SIZE) # Now we extract the metadata hash via brillo_update_payload script, which # will serve as the oracle result. payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin") metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin") cmd = ['brillo_update_payload', 'hash', '--unsigned_payload', payload.payload_file, '--signature_size', str(self.SIGNATURE_SIZE), '--metadata_hash_file', metadata_sig_file, '--payload_hash_file', payload_sig_file] proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdoutdata, _ = proc.communicate() self.assertEqual( 0, proc.returncode, 'Failed to run brillo_update_payload: {}'.format(stdoutdata)) signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file) # Finally we can compare the two signatures. with open(signed_metadata_sig_file, 'rb') as verify_fp: self.assertEqual(verify_fp.read(), metadata_signature)
def test_Sign_incremental(self): payload = self._create_payload_incremental() payload.Sign(PayloadSigner()) output_file = common.MakeTempFile(suffix='.zip') with zipfile.ZipFile(output_file, 'w') as output_zip: payload.WriteToZip(output_zip) import check_ota_package_signature check_ota_package_signature.VerifyAbOtaPayload( os.path.join(self.testdata_dir, 'testkey.x509.pem'), output_file)
def test_WriteToZip(self): payload = self._create_payload_full() payload.Sign(PayloadSigner()) output_file = common.MakeTempFile(suffix='.zip') with zipfile.ZipFile(output_file, 'w') as output_zip: payload.WriteToZip(output_zip) with zipfile.ZipFile(output_file) as verify_zip: # First make sure we have the essential entries. namelist = verify_zip.namelist() self.assertIn(Payload.PAYLOAD_BIN, namelist) self.assertIn(Payload.PAYLOAD_PROPERTIES_TXT, namelist) # Then assert these entries are stored. for entry_info in verify_zip.infolist(): if entry_info.filename not in (Payload.PAYLOAD_BIN, Payload.PAYLOAD_PROPERTIES_TXT): continue self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
def test_GetMaximumSignatureSizeInBytes_ECKey(self): signing_key = os.path.join(self.testdata_dir, 'testkey_EC.key') # pylint: disable=protected-access signature_size = PayloadSigner._GetMaximumSignatureSizeInBytes(signing_key) self.assertEqual(72, signature_size)
def test_GetPayloadMetadataOffsetAndSize(self): target_file = construct_target_files() payload = Payload() payload.Generate(target_file) payload_signer = PayloadSigner() payload.Sign(payload_signer) output_file = common.MakeTempFile(suffix='.zip') with zipfile.ZipFile(output_file, 'w') as output_zip: payload.WriteToZip(output_zip) # Find out the payload metadata offset and size. property_files = AbOtaPropertyFiles() with zipfile.ZipFile(output_file) as input_zip: # pylint: disable=protected-access payload_offset, metadata_total = ( property_files._GetPayloadMetadataOffsetAndSize(input_zip)) # The signature proto has the following format (details in # /platform/system/update_engine/update_metadata.proto): # message Signature { # optional uint32 version = 1; # optional bytes data = 2; # optional fixed32 unpadded_signature_size = 3; # } # # According to the protobuf encoding, the tail of the signature message will # be [signature string(256 bytes) + encoding of the fixed32 number 256]. And # 256 is encoded as 'x1d\x00\x01\x00\x00': # [3 (field number) << 3 | 5 (type) + byte reverse of 0x100 (256)]. # Details in (https://developers.google.com/protocol-buffers/docs/encoding) signature_tail_length = self.SIGNATURE_SIZE + 5 self.assertGreater(metadata_total, signature_tail_length) with open(output_file, 'rb') as verify_fp: verify_fp.seek(payload_offset + metadata_total - signature_tail_length) metadata_signature_proto_tail = verify_fp.read(signature_tail_length) self.assertEqual(b'\x1d\x00\x01\x00\x00', metadata_signature_proto_tail[-5:]) metadata_signature = metadata_signature_proto_tail[:-5] # Now we extract the metadata hash via brillo_update_payload script, which # will serve as the oracle result. payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin") metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin") cmd = ['brillo_update_payload', 'hash', '--unsigned_payload', payload.payload_file, '--signature_size', str(self.SIGNATURE_SIZE), '--metadata_hash_file', metadata_sig_file, '--payload_hash_file', payload_sig_file] proc = common.Run(cmd) stdoutdata, _ = proc.communicate() self.assertEqual( 0, proc.returncode, 'Failed to run brillo_update_payload:\n{}'.format(stdoutdata)) signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file) # Finally we can compare the two signatures. with open(signed_metadata_sig_file, 'rb') as verify_fp: self.assertEqual(verify_fp.read(), metadata_signature)
def test_Sign_badSigner(self): """Tests that signing failure can be captured.""" payload = self._create_payload_full() payload_signer = PayloadSigner() payload_signer.signer_args.append('bad-option') self.assertRaises(common.ExternalError, payload.Sign, payload_signer)
def test_Sign_secondary(self): payload = self._create_payload_full(secondary=True) payload.Sign(PayloadSigner()) with open(payload.payload_properties) as properties_fp: self.assertIn("SWITCH_SLOT_ON_REBOOT=0", properties_fp.read())
def test_init(self): payload_signer = PayloadSigner() self.assertEqual('openssl', payload_signer.signer)
def test_init_withExternalSigner(self): common.OPTIONS.payload_signer = 'abc' common.OPTIONS.payload_signer_args = ['arg1', 'arg2'] payload_signer = PayloadSigner() self.assertEqual('abc', payload_signer.signer) self.assertEqual(['arg1', 'arg2'], payload_signer.signer_args)
def test_init(self): payload_signer = PayloadSigner() self.assertEqual('openssl', payload_signer.signer) self.assertEqual(256, payload_signer.maximum_signature_size)