1*9e94795aSAndroid Build Coastguard Worker# 2*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2018 The Android Open Source Project 3*9e94795aSAndroid Build Coastguard Worker# 4*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*9e94795aSAndroid Build Coastguard Worker# 8*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*9e94795aSAndroid Build Coastguard Worker# 10*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*9e94795aSAndroid Build Coastguard Worker# limitations under the License. 15*9e94795aSAndroid Build Coastguard Worker# 16*9e94795aSAndroid Build Coastguard Worker 17*9e94795aSAndroid Build Coastguard Worker"""Unittests for verity_utils.py.""" 18*9e94795aSAndroid Build Coastguard Worker 19*9e94795aSAndroid Build Coastguard Workerimport copy 20*9e94795aSAndroid Build Coastguard Workerimport math 21*9e94795aSAndroid Build Coastguard Workerimport os.path 22*9e94795aSAndroid Build Coastguard Workerimport random 23*9e94795aSAndroid Build Coastguard Worker 24*9e94795aSAndroid Build Coastguard Workerimport common 25*9e94795aSAndroid Build Coastguard Workerimport sparse_img 26*9e94795aSAndroid Build Coastguard Workerfrom rangelib import RangeSet 27*9e94795aSAndroid Build Coastguard Workerfrom test_utils import ( 28*9e94795aSAndroid Build Coastguard Worker get_testdata_dir, ReleaseToolsTestCase, SkipIfExternalToolsUnavailable) 29*9e94795aSAndroid Build Coastguard Workerfrom verity_utils import ( 30*9e94795aSAndroid Build Coastguard Worker CalculateVbmetaDigest, CreateVerityImageBuilder) 31*9e94795aSAndroid Build Coastguard Worker 32*9e94795aSAndroid Build Coastguard WorkerBLOCK_SIZE = common.BLOCK_SIZE 33*9e94795aSAndroid Build Coastguard Worker 34*9e94795aSAndroid Build Coastguard Worker 35*9e94795aSAndroid Build Coastguard Workerclass VerifiedBootVersion2VerityImageBuilderTest(ReleaseToolsTestCase): 36*9e94795aSAndroid Build Coastguard Worker 37*9e94795aSAndroid Build Coastguard Worker DEFAULT_PROP_DICT = { 38*9e94795aSAndroid Build Coastguard Worker 'partition_size': str(4096 * 1024), 39*9e94795aSAndroid Build Coastguard Worker 'partition_name': 'system', 40*9e94795aSAndroid Build Coastguard Worker 'avb_avbtool': 'avbtool', 41*9e94795aSAndroid Build Coastguard Worker 'avb_hashtree_enable': 'true', 42*9e94795aSAndroid Build Coastguard Worker 'avb_add_hashtree_footer_args': '', 43*9e94795aSAndroid Build Coastguard Worker } 44*9e94795aSAndroid Build Coastguard Worker 45*9e94795aSAndroid Build Coastguard Worker def test_init(self): 46*9e94795aSAndroid Build Coastguard Worker prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT) 47*9e94795aSAndroid Build Coastguard Worker verity_image_builder = CreateVerityImageBuilder(prop_dict) 48*9e94795aSAndroid Build Coastguard Worker self.assertIsNotNone(verity_image_builder) 49*9e94795aSAndroid Build Coastguard Worker self.assertEqual(2, verity_image_builder.version) 50*9e94795aSAndroid Build Coastguard Worker 51*9e94795aSAndroid Build Coastguard Worker def test_init_MissingProps(self): 52*9e94795aSAndroid Build Coastguard Worker prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT) 53*9e94795aSAndroid Build Coastguard Worker del prop_dict['avb_hashtree_enable'] 54*9e94795aSAndroid Build Coastguard Worker verity_image_builder = CreateVerityImageBuilder(prop_dict) 55*9e94795aSAndroid Build Coastguard Worker self.assertIsNone(verity_image_builder) 56*9e94795aSAndroid Build Coastguard Worker 57*9e94795aSAndroid Build Coastguard Worker @SkipIfExternalToolsUnavailable() 58*9e94795aSAndroid Build Coastguard Worker def test_Build(self): 59*9e94795aSAndroid Build Coastguard Worker prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT) 60*9e94795aSAndroid Build Coastguard Worker verity_image_builder = CreateVerityImageBuilder(prop_dict) 61*9e94795aSAndroid Build Coastguard Worker self.assertIsNotNone(verity_image_builder) 62*9e94795aSAndroid Build Coastguard Worker self.assertEqual(2, verity_image_builder.version) 63*9e94795aSAndroid Build Coastguard Worker 64*9e94795aSAndroid Build Coastguard Worker input_dir = common.MakeTempDir() 65*9e94795aSAndroid Build Coastguard Worker image_dir = common.MakeTempDir() 66*9e94795aSAndroid Build Coastguard Worker system_image = os.path.join(image_dir, 'system.img') 67*9e94795aSAndroid Build Coastguard Worker system_image_size = verity_image_builder.CalculateMaxImageSize() 68*9e94795aSAndroid Build Coastguard Worker cmd = ['mkuserimg_mke2fs', input_dir, system_image, 'ext4', '/system', 69*9e94795aSAndroid Build Coastguard Worker str(system_image_size), '-j', '0', '-s'] 70*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput(cmd) 71*9e94795aSAndroid Build Coastguard Worker verity_image_builder.Build(system_image) 72*9e94795aSAndroid Build Coastguard Worker 73*9e94795aSAndroid Build Coastguard Worker # Additionally make vbmeta image so that we can verify with avbtool. 74*9e94795aSAndroid Build Coastguard Worker vbmeta_image = os.path.join(image_dir, 'vbmeta.img') 75*9e94795aSAndroid Build Coastguard Worker cmd = ['avbtool', 'make_vbmeta_image', '--include_descriptors_from_image', 76*9e94795aSAndroid Build Coastguard Worker system_image, '--output', vbmeta_image] 77*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput(cmd) 78*9e94795aSAndroid Build Coastguard Worker 79*9e94795aSAndroid Build Coastguard Worker # Verify the verity metadata. 80*9e94795aSAndroid Build Coastguard Worker cmd = ['avbtool', 'verify_image', '--image', vbmeta_image] 81*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput(cmd) 82*9e94795aSAndroid Build Coastguard Worker 83*9e94795aSAndroid Build Coastguard Worker def _test_CalculateMinPartitionSize_SetUp(self): 84*9e94795aSAndroid Build Coastguard Worker # To test CalculateMinPartitionSize(), by using 200MB to 2GB image size. 85*9e94795aSAndroid Build Coastguard Worker # - 51200 = 200MB * 1024 * 1024 / 4096 86*9e94795aSAndroid Build Coastguard Worker # - 524288 = 2GB * 1024 * 1024 * 1024 / 4096 87*9e94795aSAndroid Build Coastguard Worker image_sizes = [BLOCK_SIZE * random.randint(51200, 524288) + offset 88*9e94795aSAndroid Build Coastguard Worker for offset in range(BLOCK_SIZE)] 89*9e94795aSAndroid Build Coastguard Worker 90*9e94795aSAndroid Build Coastguard Worker prop_dict = { 91*9e94795aSAndroid Build Coastguard Worker 'partition_size': None, 92*9e94795aSAndroid Build Coastguard Worker 'partition_name': 'system', 93*9e94795aSAndroid Build Coastguard Worker 'avb_avbtool': 'avbtool', 94*9e94795aSAndroid Build Coastguard Worker 'avb_hashtree_enable': 'true', 95*9e94795aSAndroid Build Coastguard Worker 'avb_add_hashtree_footer_args': None, 96*9e94795aSAndroid Build Coastguard Worker } 97*9e94795aSAndroid Build Coastguard Worker builder = CreateVerityImageBuilder(prop_dict) 98*9e94795aSAndroid Build Coastguard Worker self.assertEqual(2, builder.version) 99*9e94795aSAndroid Build Coastguard Worker return image_sizes, builder 100*9e94795aSAndroid Build Coastguard Worker 101*9e94795aSAndroid Build Coastguard Worker def test_CalculateMinPartitionSize_LinearFooterSize(self): 102*9e94795aSAndroid Build Coastguard Worker """Tests with footer size which is linear to partition size.""" 103*9e94795aSAndroid Build Coastguard Worker image_sizes, builder = self._test_CalculateMinPartitionSize_SetUp() 104*9e94795aSAndroid Build Coastguard Worker for image_size in image_sizes: 105*9e94795aSAndroid Build Coastguard Worker for ratio in 0.95, 0.56, 0.22: 106*9e94795aSAndroid Build Coastguard Worker expected_size = common.RoundUpTo4K(int(math.ceil(image_size / ratio))) 107*9e94795aSAndroid Build Coastguard Worker self.assertEqual( 108*9e94795aSAndroid Build Coastguard Worker expected_size, 109*9e94795aSAndroid Build Coastguard Worker builder.CalculateMinPartitionSize( 110*9e94795aSAndroid Build Coastguard Worker image_size, lambda x, ratio=ratio: int(x * ratio))) 111*9e94795aSAndroid Build Coastguard Worker 112*9e94795aSAndroid Build Coastguard Worker def test_AVBCalcMinPartitionSize_SlowerGrowthFooterSize(self): 113*9e94795aSAndroid Build Coastguard Worker """Tests with footer size which grows slower than partition size.""" 114*9e94795aSAndroid Build Coastguard Worker 115*9e94795aSAndroid Build Coastguard Worker def _SizeCalculator(partition_size): 116*9e94795aSAndroid Build Coastguard Worker """Footer size is the power of 0.95 of partition size.""" 117*9e94795aSAndroid Build Coastguard Worker # Minus footer size to return max image size. 118*9e94795aSAndroid Build Coastguard Worker return partition_size - int(math.pow(partition_size, 0.95)) 119*9e94795aSAndroid Build Coastguard Worker 120*9e94795aSAndroid Build Coastguard Worker image_sizes, builder = self._test_CalculateMinPartitionSize_SetUp() 121*9e94795aSAndroid Build Coastguard Worker for image_size in image_sizes: 122*9e94795aSAndroid Build Coastguard Worker min_partition_size = builder.CalculateMinPartitionSize( 123*9e94795aSAndroid Build Coastguard Worker image_size, _SizeCalculator) 124*9e94795aSAndroid Build Coastguard Worker # Checks min_partition_size can accommodate image_size. 125*9e94795aSAndroid Build Coastguard Worker self.assertGreaterEqual( 126*9e94795aSAndroid Build Coastguard Worker _SizeCalculator(min_partition_size), 127*9e94795aSAndroid Build Coastguard Worker image_size) 128*9e94795aSAndroid Build Coastguard Worker # Checks min_partition_size (round to BLOCK_SIZE) is the minimum. 129*9e94795aSAndroid Build Coastguard Worker self.assertLess( 130*9e94795aSAndroid Build Coastguard Worker _SizeCalculator(min_partition_size - BLOCK_SIZE), 131*9e94795aSAndroid Build Coastguard Worker image_size) 132*9e94795aSAndroid Build Coastguard Worker 133*9e94795aSAndroid Build Coastguard Worker def test_CalculateMinPartitionSize_FasterGrowthFooterSize(self): 134*9e94795aSAndroid Build Coastguard Worker """Tests with footer size which grows faster than partition size.""" 135*9e94795aSAndroid Build Coastguard Worker 136*9e94795aSAndroid Build Coastguard Worker def _SizeCalculator(partition_size): 137*9e94795aSAndroid Build Coastguard Worker """Max image size is the power of 0.95 of partition size.""" 138*9e94795aSAndroid Build Coastguard Worker # Max image size grows less than partition size, which means 139*9e94795aSAndroid Build Coastguard Worker # footer size grows faster than partition size. 140*9e94795aSAndroid Build Coastguard Worker return int(math.pow(partition_size, 0.95)) 141*9e94795aSAndroid Build Coastguard Worker 142*9e94795aSAndroid Build Coastguard Worker image_sizes, builder = self._test_CalculateMinPartitionSize_SetUp() 143*9e94795aSAndroid Build Coastguard Worker for image_size in image_sizes: 144*9e94795aSAndroid Build Coastguard Worker min_partition_size = builder.CalculateMinPartitionSize( 145*9e94795aSAndroid Build Coastguard Worker image_size, _SizeCalculator) 146*9e94795aSAndroid Build Coastguard Worker # Checks min_partition_size can accommodate image_size. 147*9e94795aSAndroid Build Coastguard Worker self.assertGreaterEqual( 148*9e94795aSAndroid Build Coastguard Worker _SizeCalculator(min_partition_size), 149*9e94795aSAndroid Build Coastguard Worker image_size) 150*9e94795aSAndroid Build Coastguard Worker # Checks min_partition_size (round to BLOCK_SIZE) is the minimum. 151*9e94795aSAndroid Build Coastguard Worker self.assertLess( 152*9e94795aSAndroid Build Coastguard Worker _SizeCalculator(min_partition_size - BLOCK_SIZE), 153*9e94795aSAndroid Build Coastguard Worker image_size) 154*9e94795aSAndroid Build Coastguard Worker 155*9e94795aSAndroid Build Coastguard Worker @SkipIfExternalToolsUnavailable() 156*9e94795aSAndroid Build Coastguard Worker def test_CalculateVbmetaDigest(self): 157*9e94795aSAndroid Build Coastguard Worker prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT) 158*9e94795aSAndroid Build Coastguard Worker verity_image_builder = CreateVerityImageBuilder(prop_dict) 159*9e94795aSAndroid Build Coastguard Worker self.assertEqual(2, verity_image_builder.version) 160*9e94795aSAndroid Build Coastguard Worker 161*9e94795aSAndroid Build Coastguard Worker input_dir = common.MakeTempDir() 162*9e94795aSAndroid Build Coastguard Worker image_dir = common.MakeTempDir() 163*9e94795aSAndroid Build Coastguard Worker os.mkdir(os.path.join(image_dir, 'IMAGES')) 164*9e94795aSAndroid Build Coastguard Worker system_image = os.path.join(image_dir, 'IMAGES', 'system.img') 165*9e94795aSAndroid Build Coastguard Worker system_image_size = verity_image_builder.CalculateMaxImageSize() 166*9e94795aSAndroid Build Coastguard Worker cmd = ['mkuserimg_mke2fs', input_dir, system_image, 'ext4', '/system', 167*9e94795aSAndroid Build Coastguard Worker str(system_image_size), '-j', '0', '-s'] 168*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput(cmd) 169*9e94795aSAndroid Build Coastguard Worker verity_image_builder.Build(system_image) 170*9e94795aSAndroid Build Coastguard Worker 171*9e94795aSAndroid Build Coastguard Worker # Additionally make vbmeta image 172*9e94795aSAndroid Build Coastguard Worker vbmeta_image = os.path.join(image_dir, 'IMAGES', 'vbmeta.img') 173*9e94795aSAndroid Build Coastguard Worker cmd = ['avbtool', 'make_vbmeta_image', '--include_descriptors_from_image', 174*9e94795aSAndroid Build Coastguard Worker system_image, '--output', vbmeta_image] 175*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput(cmd) 176*9e94795aSAndroid Build Coastguard Worker 177*9e94795aSAndroid Build Coastguard Worker # Verify the verity metadata. 178*9e94795aSAndroid Build Coastguard Worker cmd = ['avbtool', 'verify_image', '--image', vbmeta_image] 179*9e94795aSAndroid Build Coastguard Worker common.RunAndCheckOutput(cmd) 180*9e94795aSAndroid Build Coastguard Worker digest = CalculateVbmetaDigest(image_dir, 'avbtool') 181*9e94795aSAndroid Build Coastguard Worker self.assertIsNotNone(digest) 182