blob: 7ac1cff0bb715e4d53f943edd5c0306b1e053957 [file] [log] [blame]
Tao Baoa7054ee2017-12-08 14:42:16 -08001#
2# Copyright (C) 2017 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
Tao Bao66472632017-12-04 17:16:36 -080017import base64
Tao Baobb733882019-07-24 23:31:19 -070018import io
Tao Baode1d4792018-02-20 10:05:46 -080019import os.path
Tao Baoe838d142017-12-23 23:44:48 -080020import zipfile
Tao Baoa7054ee2017-12-08 14:42:16 -080021
Tao Baoe838d142017-12-23 23:44:48 -080022import common
Tao Baode1d4792018-02-20 10:05:46 -080023import test_utils
Tao Bao66472632017-12-04 17:16:36 -080024from sign_target_files_apks import (
Seungjae Yoob3456512024-03-11 14:41:22 +090025 CheckApkAndApexKeysAvailable, EditTags, GetApkFileInfo, ParseAvbInfo,
26 ReadApexKeysInfo, ReplaceCerts, RewriteAvbProps, RewriteProps,
27 WriteOtacerts)
Tao Baoa7054ee2017-12-08 14:42:16 -080028
29
Tao Bao65b94e92018-10-11 21:57:26 -070030class SignTargetFilesApksTest(test_utils.ReleaseToolsTestCase):
Tao Baoa7054ee2017-12-08 14:42:16 -080031
Tao Bao66472632017-12-04 17:16:36 -080032 MAC_PERMISSIONS_XML = """<?xml version="1.0" encoding="iso-8859-1"?>
33<policy>
34 <signer signature="{}"><seinfo value="platform"/></signer>
35 <signer signature="{}"><seinfo value="media"/></signer>
36</policy>"""
37
Bill Peckham5c7b0342020-04-03 15:36:23 -070038 # Note that we test one apex with the partition tag, and another without to
39 # make sure that new OTA tools can process an older target files package that
40 # does not include the partition tag.
41
Tao Baoe1343992019-03-19 12:24:03 -070042 # pylint: disable=line-too-long
Bill Peckham19c3feb2020-03-20 18:31:43 -070043 APEX_KEYS_TXT = """name="apex.apexd_test.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem" container_certificate="build/make/target/product/security/testkey.x509.pem" container_private_key="build/make/target/product/security/testkey.pk8" partition="system"
Bill Peckham5c7b0342020-04-03 15:36:23 -070044name="apex.apexd_test_different_app.apex" public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" container_certificate="build/make/target/product/security/testkey.x509.pem" container_private_key="build/make/target/product/security/testkey.pk8"
Tao Baoaa7e9932019-03-15 09:37:01 -070045"""
46
Tao Baoe838d142017-12-23 23:44:48 -080047 def setUp(self):
Tao Baode1d4792018-02-20 10:05:46 -080048 self.testdata_dir = test_utils.get_testdata_dir()
Tao Baoe838d142017-12-23 23:44:48 -080049
Tao Baoa7054ee2017-12-08 14:42:16 -080050 def test_EditTags(self):
51 self.assertEqual(EditTags('dev-keys'), ('release-keys'))
52 self.assertEqual(EditTags('test-keys'), ('release-keys'))
53
54 # Multiple tags.
55 self.assertEqual(EditTags('abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
56
57 # Tags are sorted.
58 self.assertEqual(EditTags('xyz,abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
59
Tao Bao19b02fe2019-10-09 00:04:28 -070060 def test_RewriteAvbProps(self):
61 misc_info = {
62 'avb_boot_add_hash_footer_args':
63 ('--prop com.android.build.boot.os_version:R '
64 '--prop com.android.build.boot.security_patch:2019-09-05'),
Devin Mooreafdd7c72021-12-13 22:04:08 +000065 'avb_init_boot_add_hash_footer_args':
66 ('--prop com.android.build.boot.os_version:R '
67 '--prop com.android.build.boot.security_patch:2019-09-05'),
Tao Bao19b02fe2019-10-09 00:04:28 -070068 'avb_system_add_hashtree_footer_args':
69 ('--prop com.android.build.system.os_version:R '
70 '--prop com.android.build.system.security_patch:2019-09-05 '
71 '--prop com.android.build.system.fingerprint:'
72 'Android/aosp_taimen/taimen:R/QT/foo:userdebug/test-keys'),
73 'avb_vendor_add_hashtree_footer_args':
74 ('--prop com.android.build.vendor.os_version:R '
75 '--prop com.android.build.vendor.security_patch:2019-09-05 '
76 '--prop com.android.build.vendor.fingerprint:'
77 'Android/aosp_taimen/taimen:R/QT/foo:userdebug/dev-keys'),
78 }
79 expected_dict = {
80 'avb_boot_add_hash_footer_args':
81 ('--prop com.android.build.boot.os_version:R '
82 '--prop com.android.build.boot.security_patch:2019-09-05'),
Devin Mooreafdd7c72021-12-13 22:04:08 +000083 'avb_init_boot_add_hash_footer_args':
84 ('--prop com.android.build.boot.os_version:R '
85 '--prop com.android.build.boot.security_patch:2019-09-05'),
Tao Bao19b02fe2019-10-09 00:04:28 -070086 'avb_system_add_hashtree_footer_args':
87 ('--prop com.android.build.system.os_version:R '
88 '--prop com.android.build.system.security_patch:2019-09-05 '
89 '--prop com.android.build.system.fingerprint:'
90 'Android/aosp_taimen/taimen:R/QT/foo:userdebug/release-keys'),
91 'avb_vendor_add_hashtree_footer_args':
92 ('--prop com.android.build.vendor.os_version:R '
93 '--prop com.android.build.vendor.security_patch:2019-09-05 '
94 '--prop com.android.build.vendor.fingerprint:'
95 'Android/aosp_taimen/taimen:R/QT/foo:userdebug/release-keys'),
96 }
97 RewriteAvbProps(misc_info)
98 self.assertDictEqual(expected_dict, misc_info)
99
Tao Baoa7054ee2017-12-08 14:42:16 -0800100 def test_RewriteProps(self):
101 props = (
Magnus Strandh234f4b42019-05-01 23:09:30 +0200102 ('', ''),
Tao Baoa7054ee2017-12-08 14:42:16 -0800103 ('ro.build.fingerprint=foo/bar/dev-keys',
Magnus Strandh234f4b42019-05-01 23:09:30 +0200104 'ro.build.fingerprint=foo/bar/release-keys'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800105 ('ro.build.thumbprint=foo/bar/dev-keys',
Magnus Strandh234f4b42019-05-01 23:09:30 +0200106 'ro.build.thumbprint=foo/bar/release-keys'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800107 ('ro.vendor.build.fingerprint=foo/bar/dev-keys',
Magnus Strandh234f4b42019-05-01 23:09:30 +0200108 'ro.vendor.build.fingerprint=foo/bar/release-keys'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800109 ('ro.vendor.build.thumbprint=foo/bar/dev-keys',
Magnus Strandh234f4b42019-05-01 23:09:30 +0200110 'ro.vendor.build.thumbprint=foo/bar/release-keys'),
111 ('ro.odm.build.fingerprint=foo/bar/test-keys',
112 'ro.odm.build.fingerprint=foo/bar/release-keys'),
113 ('ro.odm.build.thumbprint=foo/bar/test-keys',
114 'ro.odm.build.thumbprint=foo/bar/release-keys'),
115 ('ro.product.build.fingerprint=foo/bar/dev-keys',
116 'ro.product.build.fingerprint=foo/bar/release-keys'),
117 ('ro.product.build.thumbprint=foo/bar/dev-keys',
118 'ro.product.build.thumbprint=foo/bar/release-keys'),
Justin Yun6151e3f2019-06-25 15:58:13 +0900119 ('ro.system_ext.build.fingerprint=foo/bar/test-keys',
120 'ro.system_ext.build.fingerprint=foo/bar/release-keys'),
121 ('ro.system_ext.build.thumbprint=foo/bar/test-keys',
122 'ro.system_ext.build.thumbprint=foo/bar/release-keys'),
Magnus Strandh234f4b42019-05-01 23:09:30 +0200123 ('# comment line 1', '# comment line 1'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800124 ('ro.bootimage.build.fingerprint=foo/bar/dev-keys',
Magnus Strandh234f4b42019-05-01 23:09:30 +0200125 'ro.bootimage.build.fingerprint=foo/bar/release-keys'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800126 ('ro.build.description='
127 'sailfish-user 8.0.0 OPR6.170623.012 4283428 dev-keys',
128 'ro.build.description='
Magnus Strandh234f4b42019-05-01 23:09:30 +0200129 'sailfish-user 8.0.0 OPR6.170623.012 4283428 release-keys'),
130 ('ro.build.tags=dev-keys', 'ro.build.tags=release-keys'),
131 ('ro.build.tags=test-keys', 'ro.build.tags=release-keys'),
132 ('ro.system.build.tags=dev-keys',
133 'ro.system.build.tags=release-keys'),
134 ('ro.vendor.build.tags=dev-keys',
135 'ro.vendor.build.tags=release-keys'),
136 ('ro.odm.build.tags=dev-keys',
137 'ro.odm.build.tags=release-keys'),
138 ('ro.product.build.tags=dev-keys',
139 'ro.product.build.tags=release-keys'),
Justin Yun6151e3f2019-06-25 15:58:13 +0900140 ('ro.system_ext.build.tags=dev-keys',
141 'ro.system_ext.build.tags=release-keys'),
Magnus Strandh234f4b42019-05-01 23:09:30 +0200142 ('# comment line 2', '# comment line 2'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800143 ('ro.build.display.id=OPR6.170623.012 dev-keys',
Magnus Strandh234f4b42019-05-01 23:09:30 +0200144 'ro.build.display.id=OPR6.170623.012'),
145 ('# comment line 3', '# comment line 3'),
Tao Baoa7054ee2017-12-08 14:42:16 -0800146 )
147
148 # Assert the case for each individual line.
Magnus Strandh234f4b42019-05-01 23:09:30 +0200149 for prop, expected in props:
150 self.assertEqual(expected + '\n', RewriteProps(prop))
Tao Baoa7054ee2017-12-08 14:42:16 -0800151
152 # Concatenate all the input lines.
Magnus Strandh234f4b42019-05-01 23:09:30 +0200153 self.assertEqual(
154 '\n'.join([prop[1] for prop in props]) + '\n',
155 RewriteProps('\n'.join([prop[0] for prop in props])))
Tao Baoe838d142017-12-23 23:44:48 -0800156
Tao Bao66472632017-12-04 17:16:36 -0800157 def test_ReplaceCerts(self):
158 cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
159 with open(cert1_path) as cert1_fp:
160 cert1 = cert1_fp.read()
161 cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
162 with open(cert2_path) as cert2_fp:
163 cert2 = cert2_fp.read()
164 cert3_path = os.path.join(self.testdata_dir, 'testkey.x509.pem')
165 with open(cert3_path) as cert3_fp:
166 cert3 = cert3_fp.read()
167
168 # Replace cert1 with cert3.
169 input_xml = self.MAC_PERMISSIONS_XML.format(
170 base64.b16encode(common.ParseCertificate(cert1)).lower(),
171 base64.b16encode(common.ParseCertificate(cert2)).lower())
172
173 output_xml = self.MAC_PERMISSIONS_XML.format(
174 base64.b16encode(common.ParseCertificate(cert3)).lower(),
175 base64.b16encode(common.ParseCertificate(cert2)).lower())
176
177 common.OPTIONS.key_map = {
178 cert1_path[:-9] : cert3_path[:-9],
179 }
180
181 self.assertEqual(output_xml, ReplaceCerts(input_xml))
182
183 def test_ReplaceCerts_duplicateEntries(self):
184 cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
185 with open(cert1_path) as cert1_fp:
186 cert1 = cert1_fp.read()
187 cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
188 with open(cert2_path) as cert2_fp:
189 cert2 = cert2_fp.read()
190
191 # Replace cert1 with cert2, which leads to duplicate entries.
192 input_xml = self.MAC_PERMISSIONS_XML.format(
193 base64.b16encode(common.ParseCertificate(cert1)).lower(),
194 base64.b16encode(common.ParseCertificate(cert2)).lower())
195
196 common.OPTIONS.key_map = {
197 cert1_path[:-9] : cert2_path[:-9],
198 }
199 self.assertRaises(AssertionError, ReplaceCerts, input_xml)
200
201 def test_ReplaceCerts_skipNonExistentCerts(self):
202 cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
203 with open(cert1_path) as cert1_fp:
204 cert1 = cert1_fp.read()
205 cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
206 with open(cert2_path) as cert2_fp:
207 cert2 = cert2_fp.read()
208 cert3_path = os.path.join(self.testdata_dir, 'testkey.x509.pem')
209 with open(cert3_path) as cert3_fp:
210 cert3 = cert3_fp.read()
211
212 input_xml = self.MAC_PERMISSIONS_XML.format(
213 base64.b16encode(common.ParseCertificate(cert1)).lower(),
214 base64.b16encode(common.ParseCertificate(cert2)).lower())
215
216 output_xml = self.MAC_PERMISSIONS_XML.format(
217 base64.b16encode(common.ParseCertificate(cert3)).lower(),
218 base64.b16encode(common.ParseCertificate(cert2)).lower())
219
220 common.OPTIONS.key_map = {
221 cert1_path[:-9] : cert3_path[:-9],
222 'non-existent' : cert3_path[:-9],
223 cert2_path[:-9] : 'non-existent',
224 }
225 self.assertEqual(output_xml, ReplaceCerts(input_xml))
Tao Bao11f955c2018-06-19 12:19:35 -0700226
Tao Baobb733882019-07-24 23:31:19 -0700227 def test_WriteOtacerts(self):
228 certs = [
229 os.path.join(self.testdata_dir, 'platform.x509.pem'),
230 os.path.join(self.testdata_dir, 'media.x509.pem'),
231 os.path.join(self.testdata_dir, 'testkey.x509.pem'),
232 ]
233 entry_name = 'SYSTEM/etc/security/otacerts.zip'
234 output_file = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400235 with zipfile.ZipFile(output_file, 'w', allowZip64=True) as output_zip:
Tao Baobb733882019-07-24 23:31:19 -0700236 WriteOtacerts(output_zip, entry_name, certs)
237 with zipfile.ZipFile(output_file) as input_zip:
238 self.assertIn(entry_name, input_zip.namelist())
239 otacerts_file = io.BytesIO(input_zip.read(entry_name))
240 with zipfile.ZipFile(otacerts_file) as otacerts_zip:
241 self.assertEqual(3, len(otacerts_zip.namelist()))
242
Tao Baoaa7e9932019-03-15 09:37:01 -0700243 def test_CheckApkAndApexKeysAvailable(self):
Tao Bao11f955c2018-06-19 12:19:35 -0700244 input_file = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400245 with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
Tao Bao11f955c2018-06-19 12:19:35 -0700246 input_zip.writestr('SYSTEM/app/App1.apk', "App1-content")
247 input_zip.writestr('SYSTEM/app/App2.apk.gz', "App2-content")
248
249 apk_key_map = {
250 'App1.apk' : 'key1',
251 'App2.apk' : 'key2',
252 'App3.apk' : 'key3',
253 }
254 with zipfile.ZipFile(input_file) as input_zip:
Tao Baoe1343992019-03-19 12:24:03 -0700255 CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, {})
256 CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.gz', {})
Tao Bao11f955c2018-06-19 12:19:35 -0700257
258 # 'App2.apk.gz' won't be considered as an APK.
Tao Baoe1343992019-03-19 12:24:03 -0700259 CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, {})
260 CheckApkAndApexKeysAvailable(input_zip, apk_key_map, '.xz', {})
Tao Bao11f955c2018-06-19 12:19:35 -0700261
262 del apk_key_map['App2.apk']
263 self.assertRaises(
Tao Baoaa7e9932019-03-15 09:37:01 -0700264 AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
Tao Baoe1343992019-03-19 12:24:03 -0700265 '.gz', {})
266
267 def test_CheckApkAndApexKeysAvailable_invalidApexKeys(self):
268 input_file = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400269 with zipfile.ZipFile(input_file, 'w', allowZip64=True) as input_zip:
Tao Baoe1343992019-03-19 12:24:03 -0700270 input_zip.writestr('SYSTEM/apex/Apex1.apex', "Apex1-content")
271 input_zip.writestr('SYSTEM/apex/Apex2.apex', "Apex2-content")
272
273 apk_key_map = {
274 'Apex1.apex' : 'key1',
275 'Apex2.apex' : 'key2',
276 'Apex3.apex' : 'key3',
277 }
278 apex_keys = {
Jooyung Han8caba5e2021-10-27 03:58:09 +0900279 'Apex1.apex' : ('payload-key1', 'container-key1', None),
280 'Apex2.apex' : ('payload-key2', 'container-key2', None),
Tao Baoe1343992019-03-19 12:24:03 -0700281 }
282 with zipfile.ZipFile(input_file) as input_zip:
283 CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
284
285 # Fine to have both keys as PRESIGNED.
Jooyung Han8caba5e2021-10-27 03:58:09 +0900286 apex_keys['Apex2.apex'] = ('PRESIGNED', 'PRESIGNED', None)
Tao Baoe1343992019-03-19 12:24:03 -0700287 CheckApkAndApexKeysAvailable(input_zip, apk_key_map, None, apex_keys)
288
289 # Having only one of them as PRESIGNED is not allowed.
Jooyung Han8caba5e2021-10-27 03:58:09 +0900290 apex_keys['Apex2.apex'] = ('payload-key2', 'PRESIGNED', None)
Tao Baoe1343992019-03-19 12:24:03 -0700291 self.assertRaises(
292 AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
293 None, apex_keys)
294
Jooyung Han8caba5e2021-10-27 03:58:09 +0900295 apex_keys['Apex2.apex'] = ('PRESIGNED', 'container-key1', None)
Tao Baoe1343992019-03-19 12:24:03 -0700296 self.assertRaises(
297 AssertionError, CheckApkAndApexKeysAvailable, input_zip, apk_key_map,
298 None, apex_keys)
Tao Bao11f955c2018-06-19 12:19:35 -0700299
300 def test_GetApkFileInfo(self):
Tao Bao93c2a012018-06-19 12:19:35 -0700301 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
302 "PRODUCT/apps/Chats.apk", None, [])
Tao Bao11f955c2018-06-19 12:19:35 -0700303 self.assertTrue(is_apk)
304 self.assertFalse(is_compressed)
Tao Bao93c2a012018-06-19 12:19:35 -0700305 self.assertFalse(should_be_skipped)
Tao Bao11f955c2018-06-19 12:19:35 -0700306
Tao Bao93c2a012018-06-19 12:19:35 -0700307 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
308 "PRODUCT/apps/Chats.apk", None, [])
309 self.assertTrue(is_apk)
310 self.assertFalse(is_compressed)
311 self.assertFalse(should_be_skipped)
312
313 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
314 "PRODUCT/apps/Chats.dat", None, [])
Tao Bao11f955c2018-06-19 12:19:35 -0700315 self.assertFalse(is_apk)
316 self.assertFalse(is_compressed)
Tao Bao93c2a012018-06-19 12:19:35 -0700317 self.assertFalse(should_be_skipped)
Tao Bao11f955c2018-06-19 12:19:35 -0700318
319 def test_GetApkFileInfo_withCompressedApks(self):
Tao Bao93c2a012018-06-19 12:19:35 -0700320 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
321 "PRODUCT/apps/Chats.apk.gz", ".gz", [])
Tao Bao11f955c2018-06-19 12:19:35 -0700322 self.assertTrue(is_apk)
323 self.assertTrue(is_compressed)
Tao Bao93c2a012018-06-19 12:19:35 -0700324 self.assertFalse(should_be_skipped)
Tao Bao11f955c2018-06-19 12:19:35 -0700325
Tao Bao93c2a012018-06-19 12:19:35 -0700326 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
327 "PRODUCT/apps/Chats.apk.gz", ".xz", [])
Tao Bao11f955c2018-06-19 12:19:35 -0700328 self.assertFalse(is_apk)
329 self.assertFalse(is_compressed)
Tao Bao93c2a012018-06-19 12:19:35 -0700330 self.assertFalse(should_be_skipped)
Tao Bao11f955c2018-06-19 12:19:35 -0700331
332 self.assertRaises(
Tao Bao93c2a012018-06-19 12:19:35 -0700333 AssertionError, GetApkFileInfo, "PRODUCT/apps/Chats.apk", "", [])
Tao Bao11f955c2018-06-19 12:19:35 -0700334
335 self.assertRaises(
Tao Bao93c2a012018-06-19 12:19:35 -0700336 AssertionError, GetApkFileInfo, "PRODUCT/apps/Chats.apk", "apk", [])
337
338 def test_GetApkFileInfo_withSkippedPrefixes(self):
339 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
340 "PRODUCT/preloads/apps/Chats.apk", None, set())
341 self.assertTrue(is_apk)
342 self.assertFalse(is_compressed)
343 self.assertFalse(should_be_skipped)
344
345 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
346 "PRODUCT/preloads/apps/Chats.apk",
347 None,
348 set(["PRODUCT/preloads/"]))
349 self.assertTrue(is_apk)
350 self.assertFalse(is_compressed)
351 self.assertTrue(should_be_skipped)
352
353 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
354 "SYSTEM_OTHER/preloads/apps/Chats.apk",
355 None,
356 set(["SYSTEM/preloads/", "SYSTEM_OTHER/preloads/"]))
357 self.assertTrue(is_apk)
358 self.assertFalse(is_compressed)
359 self.assertTrue(should_be_skipped)
360
361 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
362 "SYSTEM_OTHER/preloads/apps/Chats.apk.gz",
363 ".gz",
364 set(["PRODUCT/prebuilts/", "SYSTEM_OTHER/preloads/"]))
365 self.assertTrue(is_apk)
366 self.assertTrue(is_compressed)
367 self.assertTrue(should_be_skipped)
368
369 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
370 "SYSTEM_OTHER/preloads/apps/Chats.dat",
371 None,
372 set(["SYSTEM_OTHER/preloads/"]))
373 self.assertFalse(is_apk)
374 self.assertFalse(is_compressed)
375 self.assertFalse(should_be_skipped)
376
377 def test_GetApkFileInfo_checkSkippedPrefixesInput(self):
378 # set
379 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
380 "SYSTEM_OTHER/preloads/apps/Chats.apk",
381 None,
382 set(["SYSTEM_OTHER/preloads/"]))
383 self.assertTrue(is_apk)
384 self.assertFalse(is_compressed)
385 self.assertTrue(should_be_skipped)
386
387 # tuple
388 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
389 "SYSTEM_OTHER/preloads/apps/Chats.apk",
390 None,
391 ("SYSTEM_OTHER/preloads/",))
392 self.assertTrue(is_apk)
393 self.assertFalse(is_compressed)
394 self.assertTrue(should_be_skipped)
395
396 # list
397 (is_apk, is_compressed, should_be_skipped) = GetApkFileInfo(
398 "SYSTEM_OTHER/preloads/apps/Chats.apk",
399 None,
400 ["SYSTEM_OTHER/preloads/"])
401 self.assertTrue(is_apk)
402 self.assertFalse(is_compressed)
403 self.assertTrue(should_be_skipped)
404
405 # str is invalid.
406 self.assertRaises(
407 AssertionError, GetApkFileInfo, "SYSTEM_OTHER/preloads/apps/Chats.apk",
408 None, "SYSTEM_OTHER/preloads/")
409
410 # None is invalid.
411 self.assertRaises(
412 AssertionError, GetApkFileInfo, "SYSTEM_OTHER/preloads/apps/Chats.apk",
413 None, None)
Tao Baoaa7e9932019-03-15 09:37:01 -0700414
415 def test_ReadApexKeysInfo(self):
416 target_files = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400417 with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
Tao Baoaa7e9932019-03-15 09:37:01 -0700418 target_files_zip.writestr('META/apexkeys.txt', self.APEX_KEYS_TXT)
419
Kelvin Zhang928c2342020-09-22 16:15:57 -0400420 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
Melisa Carranza Zúñigada308bf2022-04-12 23:22:11 +0000421 keys_info = ReadApexKeysInfo(target_files_zip)
Tao Baoaa7e9932019-03-15 09:37:01 -0700422
Tao Baoe1343992019-03-19 12:24:03 -0700423 self.assertEqual({
424 'apex.apexd_test.apex': (
425 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900426 'build/make/target/product/security/testkey', None),
Tao Baoe1343992019-03-19 12:24:03 -0700427 'apex.apexd_test_different_app.apex': (
428 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900429 'build/make/target/product/security/testkey', None),
Tao Baoe1343992019-03-19 12:24:03 -0700430 }, keys_info)
Tao Baoaa7e9932019-03-15 09:37:01 -0700431
Tao Bao6d9e3da2019-03-26 12:59:25 -0700432 def test_ReadApexKeysInfo_mismatchingContainerKeys(self):
Tao Baoaa7e9932019-03-15 09:37:01 -0700433 # Mismatching payload public / private keys.
434 apex_keys = self.APEX_KEYS_TXT + (
435 'name="apex.apexd_test_different_app2.apex" '
436 'public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" '
Tao Bao6d9e3da2019-03-26 12:59:25 -0700437 'private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" '
Dan Willemsen0ab1be62019-04-09 21:35:37 -0700438 'container_certificate="build/make/target/product/security/testkey.x509.pem" '
Bill Peckham19c3feb2020-03-20 18:31:43 -0700439 'container_private_key="build/make/target/product/security/testkey2.pk8" '
440 'partition="system"')
Tao Baoaa7e9932019-03-15 09:37:01 -0700441 target_files = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400442 with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
Tao Baoaa7e9932019-03-15 09:37:01 -0700443 target_files_zip.writestr('META/apexkeys.txt', apex_keys)
444
Kelvin Zhang928c2342020-09-22 16:15:57 -0400445 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
Tao Baoaa7e9932019-03-15 09:37:01 -0700446 self.assertRaises(ValueError, ReadApexKeysInfo, target_files_zip)
447
Tao Bao6d9e3da2019-03-26 12:59:25 -0700448 def test_ReadApexKeysInfo_missingPayloadPrivateKey(self):
Tao Baoaa7e9932019-03-15 09:37:01 -0700449 # Invalid lines will be skipped.
450 apex_keys = self.APEX_KEYS_TXT + (
451 'name="apex.apexd_test_different_app2.apex" '
452 'public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" '
Dan Willemsen0ab1be62019-04-09 21:35:37 -0700453 'container_certificate="build/make/target/product/security/testkey.x509.pem" '
454 'container_private_key="build/make/target/product/security/testkey.pk8"')
Tao Baoaa7e9932019-03-15 09:37:01 -0700455 target_files = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400456 with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
Tao Baoaa7e9932019-03-15 09:37:01 -0700457 target_files_zip.writestr('META/apexkeys.txt', apex_keys)
458
Kelvin Zhang928c2342020-09-22 16:15:57 -0400459 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
Melisa Carranza Zúñigada308bf2022-04-12 23:22:11 +0000460 keys_info = ReadApexKeysInfo(target_files_zip)
Tao Baoaa7e9932019-03-15 09:37:01 -0700461
Tao Baoe1343992019-03-19 12:24:03 -0700462 self.assertEqual({
463 'apex.apexd_test.apex': (
464 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900465 'build/make/target/product/security/testkey', None),
Tao Baoe1343992019-03-19 12:24:03 -0700466 'apex.apexd_test_different_app.apex': (
467 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900468 'build/make/target/product/security/testkey', None),
Tao Baoe1343992019-03-19 12:24:03 -0700469 }, keys_info)
Tao Bao6d9e3da2019-03-26 12:59:25 -0700470
471 def test_ReadApexKeysInfo_missingPayloadPublicKey(self):
472 # Invalid lines will be skipped.
473 apex_keys = self.APEX_KEYS_TXT + (
474 'name="apex.apexd_test_different_app2.apex" '
475 'private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" '
Dan Willemsen0ab1be62019-04-09 21:35:37 -0700476 'container_certificate="build/make/target/product/security/testkey.x509.pem" '
477 'container_private_key="build/make/target/product/security/testkey.pk8"')
Tao Bao6d9e3da2019-03-26 12:59:25 -0700478 target_files = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400479 with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
Tao Bao6d9e3da2019-03-26 12:59:25 -0700480 target_files_zip.writestr('META/apexkeys.txt', apex_keys)
481
Kelvin Zhang928c2342020-09-22 16:15:57 -0400482 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
Melisa Carranza Zúñigada308bf2022-04-12 23:22:11 +0000483 keys_info = ReadApexKeysInfo(target_files_zip)
Tao Bao6d9e3da2019-03-26 12:59:25 -0700484
485 self.assertEqual({
486 'apex.apexd_test.apex': (
487 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900488 'build/make/target/product/security/testkey', None),
Tao Bao6d9e3da2019-03-26 12:59:25 -0700489 'apex.apexd_test_different_app.apex': (
490 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900491 'build/make/target/product/security/testkey', None),
Tao Bao6d9e3da2019-03-26 12:59:25 -0700492 }, keys_info)
Tao Baof454c3a2019-04-24 23:53:42 -0700493
494 def test_ReadApexKeysInfo_presignedKeys(self):
495 apex_keys = self.APEX_KEYS_TXT + (
496 'name="apex.apexd_test_different_app2.apex" '
497 'private_key="PRESIGNED" '
498 'public_key="PRESIGNED" '
499 'container_certificate="PRESIGNED" '
500 'container_private_key="PRESIGNED"')
501 target_files = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400502 with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
Tao Baof454c3a2019-04-24 23:53:42 -0700503 target_files_zip.writestr('META/apexkeys.txt', apex_keys)
504
Kelvin Zhang928c2342020-09-22 16:15:57 -0400505 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
Melisa Carranza Zúñigada308bf2022-04-12 23:22:11 +0000506 keys_info = ReadApexKeysInfo(target_files_zip)
Tao Baof454c3a2019-04-24 23:53:42 -0700507
508 self.assertEqual({
509 'apex.apexd_test.apex': (
510 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900511 'build/make/target/product/security/testkey', None),
Tao Baof454c3a2019-04-24 23:53:42 -0700512 'apex.apexd_test_different_app.apex': (
513 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900514 'build/make/target/product/security/testkey', None),
Tao Baof454c3a2019-04-24 23:53:42 -0700515 }, keys_info)
Tao Bao548db7d2019-04-24 23:53:42 -0700516
517 def test_ReadApexKeysInfo_presignedKeys(self):
518 apex_keys = self.APEX_KEYS_TXT + (
519 'name="apex.apexd_test_different_app2.apex" '
520 'private_key="PRESIGNED" '
521 'public_key="PRESIGNED" '
522 'container_certificate="PRESIGNED" '
523 'container_private_key="PRESIGNED"')
524 target_files = common.MakeTempFile(suffix='.zip')
Kelvin Zhang928c2342020-09-22 16:15:57 -0400525 with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
Tao Bao548db7d2019-04-24 23:53:42 -0700526 target_files_zip.writestr('META/apexkeys.txt', apex_keys)
527
Kelvin Zhang928c2342020-09-22 16:15:57 -0400528 with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
Melisa Carranza Zúñigada308bf2022-04-12 23:22:11 +0000529 keys_info = ReadApexKeysInfo(target_files_zip)
Tao Bao548db7d2019-04-24 23:53:42 -0700530
531 self.assertEqual({
532 'apex.apexd_test.apex': (
533 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900534 'build/make/target/product/security/testkey', None),
Tao Bao548db7d2019-04-24 23:53:42 -0700535 'apex.apexd_test_different_app.apex': (
536 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
Jooyung Han8caba5e2021-10-27 03:58:09 +0900537 'build/make/target/product/security/testkey', None),
Tao Bao548db7d2019-04-24 23:53:42 -0700538 }, keys_info)
Seungjae Yoob3456512024-03-11 14:41:22 +0900539
540 def test_ParseAvbInfo(self):
541 avb_info_string = """
542 Footer version: 1.0
543 Image size: 9999999 bytes
544 Original image size: 8888888 bytes
545 VBMeta offset: 7777777
546 VBMeta size: 1111 bytes
547 --
548 Minimum libavb version: 1.0
549 Header Block: 222 bytes
550 Authentication Block: 333 bytes
551 Auxiliary Block: 888 bytes
552 Public key (sha1): abababababababababababababababababababab
553 Algorithm: SHA256_RSA2048
554 Rollback Index: 0
555 Flags: 0
556 Rollback Index Location: 0
557 Release String: 'avbtool 1.3.0'
558 Descriptors:
559 Hashtree descriptor:
560 Version of dm-verity: 1
561 Image Size: 8888888 bytes
562 Tree Offset: 8888888
563 Tree Size: 44444 bytes
564 Data Block Size: 4444 bytes
565 Hash Block Size: 4444 bytes
566 FEC num roots: 0
567 FEC offset: 0
568 FEC size: 0 bytes
569 Hash Algorithm: sha1
570 Partition Name: partition-name
571 Salt: cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd
572 Root Digest: efefefefefefefefefefefefefefefefefef
573 Flags: 0
574 Prop: prop.key -> 'prop.value'
575 """
576
577 self.assertEqual(
578 {
579 'Footer version': '1.0',
580 'Image size': '9999999 bytes',
581 'Original image size': '8888888 bytes',
582 'VBMeta offset': '7777777',
583 'VBMeta size': '1111 bytes',
584 'Minimum libavb version': '1.0',
585 'Header Block': '222 bytes',
586 'Authentication Block': '333 bytes',
587 'Auxiliary Block': '888 bytes',
588 'Public key (sha1)': 'abababababababababababababababababababab',
589 'Algorithm': 'SHA256_RSA2048',
590 'Rollback Index': '0',
591 'Flags': '0',
592 'Rollback Index Location': '0',
593 'Release String': "'avbtool 1.3.0'",
594 'Descriptors': [
595 {
596 'Hashtree descriptor': {
597 'Version of dm-verity': '1',
598 'Image Size': '8888888 bytes',
599 'Tree Offset': '8888888',
600 'Tree Size': '44444 bytes',
601 'Data Block Size': '4444 bytes',
602 'Hash Block Size': '4444 bytes',
603 'FEC num roots': '0',
604 'FEC offset': '0',
605 'FEC size': '0 bytes',
606 'Hash Algorithm': 'sha1',
607 'Partition Name': 'partition-name',
608 'Salt': 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd',
609 'Root Digest': 'efefefefefefefefefefefefefefefefefef',
610 'Flags': '0',
611 }
612 },
613 {
614 'Prop': {
615 'prop.key': 'prop.value',
616 }
617 },
618 ],
619 },
620 ParseAvbInfo(avb_info_string),
621 )