1#!/usr/bin/env python3 2# 3# Copyright 2022, The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Tests certify_bootimg.""" 18 19import logging 20import glob 21import os 22import random 23import shutil 24import struct 25import subprocess 26import sys 27import tempfile 28import unittest 29 30BOOT_SIGNATURE_SIZE = 16 * 1024 31 32TEST_KERNEL_CMDLINE = ( 33 'printk.devkmsg=on firmware_class.path=/vendor/etc/ init=/init ' 34 'kfence.sample_interval=500 loop.max_part=7 bootconfig' 35) 36 37 38def generate_test_file(pathname, size, seed=None): 39 """Generates a gibberish-filled test file and returns its pathname.""" 40 random.seed(os.path.basename(pathname) if seed is None else seed) 41 with open(pathname, 'wb') as file: 42 file.write(random.randbytes(size)) 43 return pathname 44 45 46def generate_test_boot_image(boot_img, kernel_size=4096, seed='kernel', 47 avb_partition_size=None): 48 """Generates a test boot.img without a ramdisk.""" 49 with tempfile.NamedTemporaryFile() as kernel_tmpfile: 50 generate_test_file(kernel_tmpfile.name, kernel_size, seed) 51 kernel_tmpfile.flush() 52 53 mkbootimg_cmds = [ 54 'mkbootimg', 55 '--header_version', '4', 56 '--kernel', kernel_tmpfile.name, 57 '--cmdline', TEST_KERNEL_CMDLINE, 58 '--os_version', '12.0.0', 59 '--os_patch_level', '2022-03', 60 '--output', boot_img, 61 ] 62 subprocess.check_call(mkbootimg_cmds) 63 64 if avb_partition_size: 65 avbtool_cmd = ['avbtool', 'add_hash_footer', '--image', boot_img, 66 '--partition_name', 'boot', 67 '--partition_size', str(avb_partition_size)] 68 subprocess.check_call(avbtool_cmd) 69 70 71def generate_test_boot_image_archive(archive_file_name, archive_format, 72 boot_img_info, gki_info=None): 73 """Generates an archive of test boot images. 74 75 It also adds a file gki-info.txt, which contains additional settings for 76 for `certify_bootimg --extra_args`. 77 78 Args: 79 archive_file_name: the name of the archive file to create, including the 80 path, minus any format-specific extension. 81 archive_format: the |format| parameter for shutil.make_archive(). 82 e.g., 'zip', 'tar', or 'gztar', etc. 83 boot_img_info: a list of (boot_image_name, kernel_size, 84 partition_size) tuples. e.g., 85 [('boot.img', 4096, 4 * 1024), 86 ('boot-lz4.img', 8192, 8 * 1024)]. 87 gki_info: the file content to be written into 'gki-info.txt' in the 88 created archive. 89 90 Returns: 91 The full path of the created archive. e.g., /path/to/boot-img.tar.gz. 92 """ 93 with tempfile.TemporaryDirectory() as temp_out_dir: 94 for name, kernel_size, partition_size in boot_img_info: 95 boot_img = os.path.join(temp_out_dir, name) 96 generate_test_boot_image(boot_img=boot_img, 97 kernel_size=kernel_size, 98 seed=name, 99 avb_partition_size=partition_size) 100 101 if gki_info: 102 gki_info_path = os.path.join(temp_out_dir, 'gki-info.txt') 103 with open(gki_info_path, 'w', encoding='utf-8') as f: 104 f.write(gki_info) 105 106 return shutil.make_archive(archive_file_name, 107 archive_format, 108 temp_out_dir) 109 110 111def has_avb_footer(image): 112 """Returns true if the image has a avb footer.""" 113 114 avbtool_info_cmd = ['avbtool', 'info_image', '--image', image] 115 result = subprocess.run(avbtool_info_cmd, check=False, 116 stdout=subprocess.DEVNULL, 117 stderr=subprocess.DEVNULL) 118 119 return result.returncode == 0 120 121 122def get_vbmeta_size(vbmeta_bytes): 123 """Returns the total size of a AvbVBMeta image.""" 124 125 # Keep in sync with |AvbVBMetaImageHeader|. 126 AVB_MAGIC = b'AVB0' # pylint: disable=C0103 127 AVB_VBMETA_IMAGE_HEADER_SIZE = 256 # pylint: disable=C0103 128 FORMAT_STRING = ( # pylint: disable=C0103 129 '!4s2L' # magic, 2 x version. 130 '2Q' # 2 x block size: Authentication and Auxiliary blocks. 131 ) 132 133 if len(vbmeta_bytes) < struct.calcsize(FORMAT_STRING): 134 return 0 135 136 data = vbmeta_bytes[:struct.calcsize(FORMAT_STRING)] 137 (magic, _, _, 138 authentication_block_size, 139 auxiliary_data_block_size) = struct.unpack(FORMAT_STRING, data) 140 141 if magic == AVB_MAGIC: 142 return (AVB_VBMETA_IMAGE_HEADER_SIZE + 143 authentication_block_size + 144 auxiliary_data_block_size) 145 return 0 146 147 148def extract_boot_signatures(boot_img, output_dir): 149 """Extracts the boot signatures of a boot image. 150 151 This functions extracts the boot signatures of |boot_img| as: 152 - |output_dir|/boot_signature1 153 - |output_dir|/boot_signature2 154 """ 155 156 boot_img_copy = os.path.join(output_dir, 'boot_image_copy') 157 shutil.copy2(boot_img, boot_img_copy) 158 avbtool_cmd = ['avbtool', 'erase_footer', '--image', boot_img_copy] 159 subprocess.run(avbtool_cmd, check=False, stderr=subprocess.DEVNULL) 160 161 # The boot signature is assumed to be at the end of boot image, after 162 # the AVB footer is erased. 163 with open(boot_img_copy, 'rb') as image: 164 image.seek(-BOOT_SIGNATURE_SIZE, os.SEEK_END) 165 boot_signature_bytes = image.read(BOOT_SIGNATURE_SIZE) 166 assert len(boot_signature_bytes) == BOOT_SIGNATURE_SIZE 167 os.unlink(boot_img_copy) 168 169 num_signatures = 0 170 while True: 171 next_signature_size = get_vbmeta_size(boot_signature_bytes) 172 if next_signature_size <= 0: 173 break 174 175 num_signatures += 1 176 next_signature = boot_signature_bytes[:next_signature_size] 177 output_path = os.path.join( 178 output_dir, 'boot_signature' + str(num_signatures)) 179 with open(output_path, 'wb') as output: 180 output.write(next_signature) 181 182 # Moves to the next signature. 183 boot_signature_bytes = boot_signature_bytes[next_signature_size:] 184 185 186def extract_boot_archive_with_signatures(boot_img_archive, output_dir): 187 """Extracts boot images and signatures of a boot images archive. 188 189 Suppose there are two boot images in |boot_img_archive|: boot.img 190 and boot-lz4.img. This function then extracts each boot*.img and 191 their signatures as: 192 - |output_dir|/boot.img 193 - |output_dir|/boot-lz4.img 194 - |output_dir|/boot/boot_signature1 195 - |output_dir|/boot/boot_signature2 196 - |output_dir|/boot-lz4/boot_signature1 197 - |output_dir|/boot-lz4/boot_signature2 198 """ 199 shutil.unpack_archive(boot_img_archive, output_dir) 200 for boot_img in glob.glob(os.path.join(output_dir, 'boot*.img')): 201 img_name = os.path.splitext(os.path.basename(boot_img))[0] 202 signature_output_dir = os.path.join(output_dir, img_name) 203 os.mkdir(signature_output_dir, 0o777) 204 extract_boot_signatures(boot_img, signature_output_dir) 205 206 207class CertifyBootimgTest(unittest.TestCase): 208 """Tests the functionalities of certify_bootimg.""" 209 210 def setUp(self): 211 # Saves the test executable directory so that relative path references 212 # to test dependencies don't rely on being manually run from the 213 # executable directory. 214 # With this, we can just open "./testdata/testkey_rsa2048.pem" in the 215 # following tests with subprocess.run(..., cwd=self._exec_dir, ...). 216 self._exec_dir = os.path.abspath(os.path.dirname(sys.argv[0])) 217 218 # Set self.maxDiff to None to see full diff in assertion. 219 # C0103: invalid-name for maxDiff. 220 self.maxDiff = None # pylint: disable=C0103 221 222 # For AVB footers, we don't sign it so the Authentication block 223 # is zero bytes and the Algorithm is NONE. The footer will be 224 # replaced by device-specific settings when being incorporated into 225 # a device codebase. The footer here is just to pass some GKI 226 # pre-release test. 227 self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED = ( # pylint: disable=C0103 228 'Footer version: 1.0\n' 229 'Image size: 131072 bytes\n' 230 'Original image size: 24576 bytes\n' 231 'VBMeta offset: 24576\n' 232 'VBMeta size: 576 bytes\n' 233 '--\n' 234 'Minimum libavb version: 1.0\n' 235 'Header Block: 256 bytes\n' 236 'Authentication Block: 0 bytes\n' 237 'Auxiliary Block: 320 bytes\n' 238 'Algorithm: NONE\n' 239 'Rollback Index: 0\n' 240 'Flags: 0\n' 241 'Rollback Index Location: 0\n' 242 "Release String: 'avbtool 1.3.0'\n" 243 'Descriptors:\n' 244 ' Hash descriptor:\n' 245 ' Image Size: 24576 bytes\n' 246 ' Hash Algorithm: sha256\n' 247 ' Partition Name: boot\n' 248 ' Salt: a11ba11b\n' 249 ' Digest: ' 250 '0dcbb90bc005403e79eef4209a5ac6fc' 251 '02c3d5c5f3abae9d07570ef8e4ca9b98\n' 252 ' Flags: 0\n' 253 " Prop: avb -> 'nice'\n" 254 " Prop: avb_space -> 'nice to meet you'\n" 255 ) 256 257 self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED_2 = ( # pylint: disable=C0103 258 'Footer version: 1.0\n' 259 'Image size: 131072 bytes\n' 260 'Original image size: 24576 bytes\n' 261 'VBMeta offset: 24576\n' 262 'VBMeta size: 576 bytes\n' 263 '--\n' 264 'Minimum libavb version: 1.0\n' 265 'Header Block: 256 bytes\n' 266 'Authentication Block: 0 bytes\n' 267 'Auxiliary Block: 320 bytes\n' 268 'Algorithm: NONE\n' 269 'Rollback Index: 0\n' 270 'Flags: 0\n' 271 'Rollback Index Location: 0\n' 272 "Release String: 'avbtool 1.3.0'\n" 273 'Descriptors:\n' 274 ' Hash descriptor:\n' 275 ' Image Size: 24576 bytes\n' 276 ' Hash Algorithm: sha256\n' 277 ' Partition Name: boot\n' 278 ' Salt: a11ba11b\n' 279 ' Digest: ' 280 '54b0f4babe7f8fd1c204b6bfffbbe200' 281 'b9ccb8499776fc50f110344380cc1bf9\n' 282 ' Flags: 0\n' 283 " Prop: avb -> 'nice'\n" 284 " Prop: avb_space -> 'nice to meet you'\n" 285 ) 286 287 self._EXPECTED_AVB_FOOTER_WITH_GKI_INFO = ( # pylint: disable=C0103 288 'Footer version: 1.0\n' 289 'Image size: 131072 bytes\n' 290 'Original image size: 24576 bytes\n' 291 'VBMeta offset: 24576\n' 292 'VBMeta size: 704 bytes\n' 293 '--\n' 294 'Minimum libavb version: 1.0\n' 295 'Header Block: 256 bytes\n' 296 'Authentication Block: 0 bytes\n' 297 'Auxiliary Block: 448 bytes\n' 298 'Algorithm: NONE\n' 299 'Rollback Index: 0\n' 300 'Flags: 0\n' 301 'Rollback Index Location: 0\n' 302 "Release String: 'avbtool 1.3.0'\n" 303 'Descriptors:\n' 304 ' Hash descriptor:\n' 305 ' Image Size: 24576 bytes\n' 306 ' Hash Algorithm: sha256\n' 307 ' Partition Name: boot\n' 308 ' Salt: a11ba11b\n' 309 ' Digest: ' 310 '9501fb3e889f926976e1566bb748c891' 311 '0c0a0837108764262fa1ecc413056cf8\n' 312 ' Flags: 0\n' 313 " Prop: avb -> 'nice'\n" 314 " Prop: avb_space -> 'nice to meet you'\n" 315 " Prop: com.android.build.boot.os_version -> '13'\n" 316 " Prop: com.android.build.boot.security_patch -> '2022-05-05'\n" 317 ) 318 319 self._EXPECTED_AVB_FOOTER_BOOT = ( # pylint: disable=C0103 320 'Footer version: 1.0\n' 321 'Image size: 131072 bytes\n' 322 'Original image size: 28672 bytes\n' 323 'VBMeta offset: 28672\n' 324 'VBMeta size: 704 bytes\n' 325 '--\n' 326 'Minimum libavb version: 1.0\n' 327 'Header Block: 256 bytes\n' 328 'Authentication Block: 0 bytes\n' 329 'Auxiliary Block: 448 bytes\n' 330 'Algorithm: NONE\n' 331 'Rollback Index: 0\n' 332 'Flags: 0\n' 333 'Rollback Index Location: 0\n' 334 "Release String: 'avbtool 1.3.0'\n" 335 'Descriptors:\n' 336 ' Hash descriptor:\n' 337 ' Image Size: 28672 bytes\n' 338 ' Hash Algorithm: sha256\n' 339 ' Partition Name: boot\n' 340 ' Salt: a11ba11b\n' 341 ' Digest: ' 342 '925ee1495c95d302c4a2c8c2edaf29c8' 343 '41b1c8ae2ae7bf5d46561d21b7494cb3\n' 344 ' Flags: 0\n' 345 " Prop: avb -> 'nice'\n" 346 " Prop: avb_space -> 'nice to meet you'\n" 347 " Prop: com.android.build.boot.os_version -> '13'\n" 348 " Prop: com.android.build.boot.security_patch -> '2022-05-05'\n" 349 ) 350 351 self._EXPECTED_AVB_FOOTER_BOOT_LZ4 = ( # pylint: disable=C0103 352 'Footer version: 1.0\n' 353 'Image size: 262144 bytes\n' 354 'Original image size: 36864 bytes\n' 355 'VBMeta offset: 36864\n' 356 'VBMeta size: 704 bytes\n' 357 '--\n' 358 'Minimum libavb version: 1.0\n' 359 'Header Block: 256 bytes\n' 360 'Authentication Block: 0 bytes\n' 361 'Auxiliary Block: 448 bytes\n' 362 'Algorithm: NONE\n' 363 'Rollback Index: 0\n' 364 'Flags: 0\n' 365 'Rollback Index Location: 0\n' 366 "Release String: 'avbtool 1.3.0'\n" 367 'Descriptors:\n' 368 ' Hash descriptor:\n' 369 ' Image Size: 36864 bytes\n' 370 ' Hash Algorithm: sha256\n' 371 ' Partition Name: boot\n' 372 ' Salt: a11ba11b\n' 373 ' Digest: ' 374 'a390b4febe92d0331b44edacaad54ad8' 375 '972aaa05bb4ea427697c132b7e3741a2\n' 376 ' Flags: 0\n' 377 " Prop: avb -> 'nice'\n" 378 " Prop: avb_space -> 'nice to meet you'\n" 379 " Prop: com.android.build.boot.os_version -> '13'\n" 380 " Prop: com.android.build.boot.security_patch -> '2022-05-05'\n" 381 ) 382 383 self._EXPECTED_AVB_FOOTER_BOOT_GZ = ( # pylint: disable=C0103 384 'Footer version: 1.0\n' 385 'Image size: 131072 bytes\n' 386 'Original image size: 28672 bytes\n' 387 'VBMeta offset: 28672\n' 388 'VBMeta size: 576 bytes\n' 389 '--\n' 390 'Minimum libavb version: 1.0\n' 391 'Header Block: 256 bytes\n' 392 'Authentication Block: 0 bytes\n' 393 'Auxiliary Block: 320 bytes\n' 394 'Algorithm: NONE\n' 395 'Rollback Index: 0\n' 396 'Flags: 0\n' 397 'Rollback Index Location: 0\n' 398 "Release String: 'avbtool 1.3.0'\n" 399 'Descriptors:\n' 400 ' Hash descriptor:\n' 401 ' Image Size: 28672 bytes\n' 402 ' Hash Algorithm: sha256\n' 403 ' Partition Name: boot\n' 404 ' Salt: a11ba11b\n' 405 ' Digest: ' 406 '3808076404808e468a0a9df34c6d9d7a' 407 '8dc8ae69fb03fa62f0f23aa5b65e3c66\n' 408 ' Flags: 0\n' 409 " Prop: avb -> 'nice'\n" 410 " Prop: avb_space -> 'nice to meet you'\n" 411 ) 412 413 self._EXPECTED_BOOT_SIGNATURE_RSA2048 = ( # pylint: disable=C0103 414 'Minimum libavb version: 1.0\n' 415 'Header Block: 256 bytes\n' 416 'Authentication Block: 320 bytes\n' 417 'Auxiliary Block: 832 bytes\n' 418 'Public key (sha1): ' 419 'cdbb77177f731920bbe0a0f94f84d9038ae0617d\n' 420 'Algorithm: SHA256_RSA2048\n' 421 'Rollback Index: 0\n' 422 'Flags: 0\n' 423 'Rollback Index Location: 0\n' 424 "Release String: 'avbtool 1.3.0'\n" 425 'Descriptors:\n' 426 ' Hash descriptor:\n' 427 ' Image Size: 8192 bytes\n' 428 ' Hash Algorithm: sha256\n' 429 ' Partition Name: boot\n' # boot 430 ' Salt: d00df00d\n' 431 ' Digest: ' 432 'faf1da72a4fba97ddab0b8f7a410db86' 433 '8fb72392a66d1440ff8bff490c73c771\n' 434 ' Flags: 0\n' 435 " Prop: gki -> 'nice'\n" 436 " Prop: space -> 'nice to meet you'\n" 437 ) 438 439 self._EXPECTED_KERNEL_SIGNATURE_RSA2048 = ( # pylint: disable=C0103 440 'Minimum libavb version: 1.0\n' 441 'Header Block: 256 bytes\n' 442 'Authentication Block: 320 bytes\n' 443 'Auxiliary Block: 832 bytes\n' 444 'Public key (sha1): ' 445 'cdbb77177f731920bbe0a0f94f84d9038ae0617d\n' 446 'Algorithm: SHA256_RSA2048\n' 447 'Rollback Index: 0\n' 448 'Flags: 0\n' 449 'Rollback Index Location: 0\n' 450 "Release String: 'avbtool 1.3.0'\n" 451 'Descriptors:\n' 452 ' Hash descriptor:\n' 453 ' Image Size: 4096 bytes\n' 454 ' Hash Algorithm: sha256\n' 455 ' Partition Name: generic_kernel\n' # generic_kernel 456 ' Salt: d00df00d\n' 457 ' Digest: ' 458 '762c877f3af0d50a4a4fbc1385d5c7ce' 459 '52a1288db74b33b72217d93db6f2909f\n' 460 ' Flags: 0\n' 461 " Prop: gki -> 'nice'\n" 462 " Prop: space -> 'nice to meet you'\n" 463 ) 464 465 self._EXPECTED_BOOT_SIGNATURE_RSA4096 = ( # pylint: disable=C0103 466 'Minimum libavb version: 1.0\n' 467 'Header Block: 256 bytes\n' 468 'Authentication Block: 576 bytes\n' 469 'Auxiliary Block: 1344 bytes\n' 470 'Public key (sha1): ' 471 '2597c218aae470a130f61162feaae70afd97f011\n' 472 'Algorithm: SHA256_RSA4096\n' # RSA4096 473 'Rollback Index: 0\n' 474 'Flags: 0\n' 475 'Rollback Index Location: 0\n' 476 "Release String: 'avbtool 1.3.0'\n" 477 'Descriptors:\n' 478 ' Hash descriptor:\n' 479 ' Image Size: 8192 bytes\n' 480 ' Hash Algorithm: sha256\n' 481 ' Partition Name: boot\n' # boot 482 ' Salt: d00df00d\n' 483 ' Digest: ' 484 'faf1da72a4fba97ddab0b8f7a410db86' 485 '8fb72392a66d1440ff8bff490c73c771\n' 486 ' Flags: 0\n' 487 " Prop: gki -> 'nice'\n" 488 " Prop: space -> 'nice to meet you'\n" 489 ) 490 491 self._EXPECTED_KERNEL_SIGNATURE_RSA4096 = ( # pylint: disable=C0103 492 'Minimum libavb version: 1.0\n' 493 'Header Block: 256 bytes\n' 494 'Authentication Block: 576 bytes\n' 495 'Auxiliary Block: 1344 bytes\n' 496 'Public key (sha1): ' 497 '2597c218aae470a130f61162feaae70afd97f011\n' 498 'Algorithm: SHA256_RSA4096\n' # RSA4096 499 'Rollback Index: 0\n' 500 'Flags: 0\n' 501 'Rollback Index Location: 0\n' 502 "Release String: 'avbtool 1.3.0'\n" 503 'Descriptors:\n' 504 ' Hash descriptor:\n' 505 ' Image Size: 4096 bytes\n' 506 ' Hash Algorithm: sha256\n' 507 ' Partition Name: generic_kernel\n' # generic_kernel 508 ' Salt: d00df00d\n' 509 ' Digest: ' 510 '762c877f3af0d50a4a4fbc1385d5c7ce' 511 '52a1288db74b33b72217d93db6f2909f\n' 512 ' Flags: 0\n' 513 " Prop: gki -> 'nice'\n" 514 " Prop: space -> 'nice to meet you'\n" 515 ) 516 517 self._EXPECTED_BOOT_SIGNATURE_WITH_GKI_INFO = ( # pylint: disable=C0103 518 'Minimum libavb version: 1.0\n' 519 'Header Block: 256 bytes\n' 520 'Authentication Block: 576 bytes\n' 521 'Auxiliary Block: 1600 bytes\n' 522 'Public key (sha1): ' 523 '2597c218aae470a130f61162feaae70afd97f011\n' 524 'Algorithm: SHA256_RSA4096\n' # RSA4096 525 'Rollback Index: 0\n' 526 'Flags: 0\n' 527 'Rollback Index Location: 0\n' 528 "Release String: 'avbtool 1.3.0'\n" 529 'Descriptors:\n' 530 ' Hash descriptor:\n' 531 ' Image Size: 8192 bytes\n' 532 ' Hash Algorithm: sha256\n' 533 ' Partition Name: boot\n' # boot 534 ' Salt: d00df00d\n' 535 ' Digest: ' 536 'faf1da72a4fba97ddab0b8f7a410db86' 537 '8fb72392a66d1440ff8bff490c73c771\n' 538 ' Flags: 0\n' 539 " Prop: gki -> 'nice'\n" 540 " Prop: space -> 'nice to meet you'\n" 541 " Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-" 542 "ged21d463f856'\n" 543 " Prop: BRANCH -> 'android13-5.10-2022-05'\n" 544 " Prop: BUILD_NUMBER -> 'ab8295296'\n" 545 " Prop: GKI_INFO -> 'added here'\n" 546 ) 547 548 self._EXPECTED_KERNEL_SIGNATURE_WITH_GKI_INFO = (# pylint: disable=C0103 549 'Minimum libavb version: 1.0\n' 550 'Header Block: 256 bytes\n' 551 'Authentication Block: 576 bytes\n' 552 'Auxiliary Block: 1600 bytes\n' 553 'Public key (sha1): ' 554 '2597c218aae470a130f61162feaae70afd97f011\n' 555 'Algorithm: SHA256_RSA4096\n' # RSA4096 556 'Rollback Index: 0\n' 557 'Flags: 0\n' 558 'Rollback Index Location: 0\n' 559 "Release String: 'avbtool 1.3.0'\n" 560 'Descriptors:\n' 561 ' Hash descriptor:\n' 562 ' Image Size: 4096 bytes\n' 563 ' Hash Algorithm: sha256\n' 564 ' Partition Name: generic_kernel\n' # generic_kernel 565 ' Salt: d00df00d\n' 566 ' Digest: ' 567 '762c877f3af0d50a4a4fbc1385d5c7ce' 568 '52a1288db74b33b72217d93db6f2909f\n' 569 ' Flags: 0\n' 570 " Prop: gki -> 'nice'\n" 571 " Prop: space -> 'nice to meet you'\n" 572 " Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-" 573 "ged21d463f856'\n" 574 " Prop: BRANCH -> 'android13-5.10-2022-05'\n" 575 " Prop: BUILD_NUMBER -> 'ab8295296'\n" 576 " Prop: GKI_INFO -> 'added here'\n" 577 ) 578 579 self._EXPECTED_BOOT_SIGNATURE1_RSA4096 = ( # pylint: disable=C0103 580 'Minimum libavb version: 1.0\n' 581 'Header Block: 256 bytes\n' 582 'Authentication Block: 576 bytes\n' 583 'Auxiliary Block: 1600 bytes\n' 584 'Public key (sha1): ' 585 '2597c218aae470a130f61162feaae70afd97f011\n' 586 'Algorithm: SHA256_RSA4096\n' # RSA4096 587 'Rollback Index: 0\n' 588 'Flags: 0\n' 589 'Rollback Index Location: 0\n' 590 "Release String: 'avbtool 1.3.0'\n" 591 'Descriptors:\n' 592 ' Hash descriptor:\n' 593 ' Image Size: 12288 bytes\n' 594 ' Hash Algorithm: sha256\n' 595 ' Partition Name: boot\n' # boot 596 ' Salt: d00df00d\n' 597 ' Digest: ' 598 '30208b4d0a6d16db47fc13c9527bfe81' 599 'a168d3b3940325d1ca8d3439792bfe18\n' 600 ' Flags: 0\n' 601 " Prop: gki -> 'nice'\n" 602 " Prop: space -> 'nice to meet you'\n" 603 " Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-" 604 "ged21d463f856'\n" 605 " Prop: BRANCH -> 'android13-5.10-2022-05'\n" 606 " Prop: BUILD_NUMBER -> 'ab8295296'\n" 607 " Prop: SPACE -> 'nice to meet you'\n" 608 ) 609 610 self._EXPECTED_BOOT_SIGNATURE2_RSA4096 = ( # pylint: disable=C0103 611 'Minimum libavb version: 1.0\n' 612 'Header Block: 256 bytes\n' 613 'Authentication Block: 576 bytes\n' 614 'Auxiliary Block: 1600 bytes\n' 615 'Public key (sha1): ' 616 '2597c218aae470a130f61162feaae70afd97f011\n' 617 'Algorithm: SHA256_RSA4096\n' # RSA4096 618 'Rollback Index: 0\n' 619 'Flags: 0\n' 620 'Rollback Index Location: 0\n' 621 "Release String: 'avbtool 1.3.0'\n" 622 'Descriptors:\n' 623 ' Hash descriptor:\n' 624 ' Image Size: 8192 bytes\n' 625 ' Hash Algorithm: sha256\n' 626 ' Partition Name: generic_kernel\n' # generic_kernel 627 ' Salt: d00df00d\n' 628 ' Digest: ' 629 'd4c8847e7d9900a98f77e1f0b5272854' 630 '7bf9c1e428fea500d419275f72ec5bd6\n' 631 ' Flags: 0\n' 632 " Prop: gki -> 'nice'\n" 633 " Prop: space -> 'nice to meet you'\n" 634 " Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-" 635 "ged21d463f856'\n" 636 " Prop: BRANCH -> 'android13-5.10-2022-05'\n" 637 " Prop: BUILD_NUMBER -> 'ab8295296'\n" 638 " Prop: SPACE -> 'nice to meet you'\n" 639 ) 640 641 self._EXPECTED_BOOT_LZ4_SIGNATURE1_RSA4096 = ( # pylint: disable=C0103 642 'Minimum libavb version: 1.0\n' 643 'Header Block: 256 bytes\n' 644 'Authentication Block: 576 bytes\n' 645 'Auxiliary Block: 1600 bytes\n' 646 'Public key (sha1): ' 647 '2597c218aae470a130f61162feaae70afd97f011\n' 648 'Algorithm: SHA256_RSA4096\n' # RSA4096 649 'Rollback Index: 0\n' 650 'Flags: 0\n' 651 'Rollback Index Location: 0\n' 652 "Release String: 'avbtool 1.3.0'\n" 653 'Descriptors:\n' 654 ' Hash descriptor:\n' 655 ' Image Size: 20480 bytes\n' 656 ' Hash Algorithm: sha256\n' 657 ' Partition Name: boot\n' # boot 658 ' Salt: d00df00d\n' 659 ' Digest: ' 660 '9d3a0670a9fd3de66e940117ef97700f' 661 'ed5fd1c6fb90798fd3873af45fc91cb4\n' 662 ' Flags: 0\n' 663 " Prop: gki -> 'nice'\n" 664 " Prop: space -> 'nice to meet you'\n" 665 " Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-" 666 "ged21d463f856'\n" 667 " Prop: BRANCH -> 'android13-5.10-2022-05'\n" 668 " Prop: BUILD_NUMBER -> 'ab8295296'\n" 669 " Prop: SPACE -> 'nice to meet you'\n" 670 ) 671 672 self._EXPECTED_BOOT_LZ4_SIGNATURE2_RSA4096 = ( # pylint: disable=C0103 673 'Minimum libavb version: 1.0\n' 674 'Header Block: 256 bytes\n' 675 'Authentication Block: 576 bytes\n' 676 'Auxiliary Block: 1600 bytes\n' 677 'Public key (sha1): ' 678 '2597c218aae470a130f61162feaae70afd97f011\n' 679 'Algorithm: SHA256_RSA4096\n' # RSA4096 680 'Rollback Index: 0\n' 681 'Flags: 0\n' 682 'Rollback Index Location: 0\n' 683 "Release String: 'avbtool 1.3.0'\n" 684 'Descriptors:\n' 685 ' Hash descriptor:\n' 686 ' Image Size: 16384 bytes\n' 687 ' Hash Algorithm: sha256\n' 688 ' Partition Name: generic_kernel\n' # generic_kernel 689 ' Salt: d00df00d\n' 690 ' Digest: ' 691 '7d109e3dccca9e30e04249162d07e58c' 692 '62fdf269804b35857b956fba339b2679\n' 693 ' Flags: 0\n' 694 " Prop: gki -> 'nice'\n" 695 " Prop: space -> 'nice to meet you'\n" 696 " Prop: KERNEL_RELEASE -> '5.10.42-android13-0-00544-" 697 "ged21d463f856'\n" 698 " Prop: BRANCH -> 'android13-5.10-2022-05'\n" 699 " Prop: BUILD_NUMBER -> 'ab8295296'\n" 700 " Prop: SPACE -> 'nice to meet you'\n" 701 ) 702 703 self._EXPECTED_BOOT_GZ_SIGNATURE1_RSA4096 = ( # pylint: disable=C0103 704 'Minimum libavb version: 1.0\n' 705 'Header Block: 256 bytes\n' 706 'Authentication Block: 576 bytes\n' 707 'Auxiliary Block: 1344 bytes\n' 708 'Public key (sha1): ' 709 '2597c218aae470a130f61162feaae70afd97f011\n' 710 'Algorithm: SHA256_RSA4096\n' # RSA4096 711 'Rollback Index: 0\n' 712 'Flags: 0\n' 713 'Rollback Index Location: 0\n' 714 "Release String: 'avbtool 1.3.0'\n" 715 'Descriptors:\n' 716 ' Hash descriptor:\n' 717 ' Image Size: 12288 bytes\n' 718 ' Hash Algorithm: sha256\n' 719 ' Partition Name: boot\n' # boot 720 ' Salt: d00df00d\n' 721 ' Digest: ' 722 '6fcddc6167ae3c2037b424d35c3ef107' 723 'f586510dbb2d652d7c08b88e6ea52fc6\n' 724 ' Flags: 0\n' 725 " Prop: gki -> 'nice'\n" 726 " Prop: space -> 'nice to meet you'\n" 727 ) 728 729 self._EXPECTED_BOOT_GZ_SIGNATURE2_RSA4096 = ( # pylint: disable=C0103 730 'Minimum libavb version: 1.0\n' 731 'Header Block: 256 bytes\n' 732 'Authentication Block: 576 bytes\n' 733 'Auxiliary Block: 1344 bytes\n' 734 'Public key (sha1): ' 735 '2597c218aae470a130f61162feaae70afd97f011\n' 736 'Algorithm: SHA256_RSA4096\n' # RSA4096 737 'Rollback Index: 0\n' 738 'Flags: 0\n' 739 'Rollback Index Location: 0\n' 740 "Release String: 'avbtool 1.3.0'\n" 741 'Descriptors:\n' 742 ' Hash descriptor:\n' 743 ' Image Size: 8192 bytes\n' 744 ' Hash Algorithm: sha256\n' 745 ' Partition Name: generic_kernel\n' # generic_kernel 746 ' Salt: d00df00d\n' 747 ' Digest: ' 748 '7a6a43eb4048b783346fb6d039103647' 749 '6c4313146da521467af282dff1838d0e\n' 750 ' Flags: 0\n' 751 " Prop: gki -> 'nice'\n" 752 " Prop: space -> 'nice to meet you'\n" 753 ) 754 755 def _test_boot_signatures(self, signatures_dir, expected_signatures_info): 756 """Tests the info of each boot signature under the signature directory. 757 758 Args: 759 signatures_dir: the directory containing the boot signatures. e.g., 760 - signatures_dir/boot_signature1 761 - signatures_dir/boot_signature2 762 expected_signatures_info: A dict containing the expected output 763 of `avbtool info_image` for each signature under 764 |signatures_dir|. e.g., 765 {'boot_signature1': expected_stdout_signature1 766 'boot_signature2': expected_stdout_signature2} 767 """ 768 for signature in expected_signatures_info: 769 avbtool_info_cmds = [ 770 'avbtool', 'info_image', '--image', 771 os.path.join(signatures_dir, signature) 772 ] 773 result = subprocess.run(avbtool_info_cmds, check=True, 774 capture_output=True, encoding='utf-8') 775 self.assertEqual(result.stdout, expected_signatures_info[signature]) 776 777 def test_certify_bootimg_without_avb_footer(self): 778 """Tests certify_bootimg on a boot image without an AVB footer.""" 779 with tempfile.TemporaryDirectory() as temp_out_dir: 780 boot_img = os.path.join(temp_out_dir, 'boot.img') 781 generate_test_boot_image(boot_img) 782 783 # Generates the certified boot image, with a RSA2048 key. 784 boot_certified_img = os.path.join(temp_out_dir, 785 'boot-certified.img') 786 certify_bootimg_cmds = [ 787 'certify_bootimg', 788 '--boot_img', boot_img, 789 '--algorithm', 'SHA256_RSA2048', 790 '--key', './testdata/testkey_rsa2048.pem', 791 '--extra_args', '--prop gki:nice ' 792 '--prop space:"nice to meet you"', 793 '--output', boot_certified_img, 794 ] 795 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 796 797 extract_boot_signatures(boot_certified_img, temp_out_dir) 798 self._test_boot_signatures( 799 temp_out_dir, 800 {'boot_signature1': self._EXPECTED_BOOT_SIGNATURE_RSA2048, 801 'boot_signature2': self._EXPECTED_KERNEL_SIGNATURE_RSA2048}) 802 803 # Generates the certified boot image again, with a RSA4096 key. 804 boot_certified2_img = os.path.join(temp_out_dir, 805 'boot-certified2.img') 806 certify_bootimg_cmds = [ 807 'certify_bootimg', 808 '--boot_img', boot_certified_img, 809 '--algorithm', 'SHA256_RSA4096', 810 '--key', './testdata/testkey_rsa4096.pem', 811 '--extra_args', '--prop gki:nice ' 812 '--prop space:"nice to meet you"', 813 '--output', boot_certified2_img, 814 ] 815 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 816 817 extract_boot_signatures(boot_certified2_img, temp_out_dir) 818 self._test_boot_signatures( 819 temp_out_dir, 820 {'boot_signature1': self._EXPECTED_BOOT_SIGNATURE_RSA4096, 821 'boot_signature2': self._EXPECTED_KERNEL_SIGNATURE_RSA4096}) 822 823 def test_certify_bootimg_with_avb_footer(self): 824 """Tests the AVB footer location remains after certify_bootimg.""" 825 with tempfile.TemporaryDirectory() as temp_out_dir: 826 boot_img = os.path.join(temp_out_dir, 'boot.img') 827 generate_test_boot_image(boot_img=boot_img, 828 avb_partition_size=128 * 1024) 829 self.assertTrue(has_avb_footer(boot_img)) 830 831 # Generates the certified boot image, with a RSA2048 key. 832 boot_certified_img = os.path.join(temp_out_dir, 833 'boot-certified.img') 834 certify_bootimg_cmds = [ 835 'certify_bootimg', 836 '--boot_img', boot_img, 837 '--algorithm', 'SHA256_RSA2048', 838 '--key', './testdata/testkey_rsa2048.pem', 839 '--extra_args', '--prop gki:nice ' 840 '--prop space:"nice to meet you"', 841 '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' 842 '--prop avb_space:"nice to meet you"', 843 '--output', boot_certified_img, 844 ] 845 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 846 847 # Checks an AVB footer exists and the image size remains. 848 self.assertTrue(has_avb_footer(boot_certified_img)) 849 self.assertEqual(os.path.getsize(boot_img), 850 os.path.getsize(boot_certified_img)) 851 # Checks the content in the AVB footer. 852 self._test_boot_signatures( 853 temp_out_dir, 854 {'boot-certified.img': 855 self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED}) 856 857 # Checks the content in the GKI certificate. 858 extract_boot_signatures(boot_certified_img, temp_out_dir) 859 self._test_boot_signatures( 860 temp_out_dir, 861 {'boot_signature1': self._EXPECTED_BOOT_SIGNATURE_RSA2048, 862 'boot_signature2': self._EXPECTED_KERNEL_SIGNATURE_RSA2048}) 863 864 # Generates the certified boot image again, with a RSA4096 key. 865 boot_certified2_img = os.path.join(temp_out_dir, 866 'boot-certified2.img') 867 certify_bootimg_cmds = [ 868 'certify_bootimg', 869 '--boot_img', boot_certified_img, 870 '--algorithm', 'SHA256_RSA4096', 871 '--key', './testdata/testkey_rsa4096.pem', 872 '--extra_args', '--prop gki:nice ' 873 '--prop space:"nice to meet you"', 874 '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' 875 '--prop avb_space:"nice to meet you"', 876 '--output', boot_certified2_img, 877 ] 878 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 879 880 # Checks an AVB footer exists and the image size remains. 881 self.assertTrue(has_avb_footer(boot_certified2_img)) 882 self.assertEqual(os.path.getsize(boot_certified_img), 883 os.path.getsize(boot_certified2_img)) 884 # Checks the content in the AVB footer. 885 self._test_boot_signatures( 886 temp_out_dir, 887 {'boot-certified2.img': 888 self._EXPECTED_AVB_FOOTER_BOOT_CERTIFIED_2}) 889 890 # Checks the content in the GKI certificate. 891 extract_boot_signatures(boot_certified2_img, temp_out_dir) 892 self._test_boot_signatures( 893 temp_out_dir, 894 {'boot_signature1': self._EXPECTED_BOOT_SIGNATURE_RSA4096, 895 'boot_signature2': self._EXPECTED_KERNEL_SIGNATURE_RSA4096}) 896 897 def test_certify_bootimg_with_gki_info(self): 898 """Tests certify_bootimg with --gki_info.""" 899 with tempfile.TemporaryDirectory() as temp_out_dir: 900 boot_img = os.path.join(temp_out_dir, 'boot.img') 901 generate_test_boot_image(boot_img=boot_img, 902 avb_partition_size=128 * 1024) 903 self.assertTrue(has_avb_footer(boot_img)) 904 905 gki_info = ('certify_bootimg_extra_args=' 906 '--prop KERNEL_RELEASE:5.10.42' 907 '-android13-0-00544-ged21d463f856 ' 908 '--prop BRANCH:android13-5.10-2022-05 ' 909 '--prop BUILD_NUMBER:ab8295296 ' 910 '--prop GKI_INFO:"added here"\n' 911 'certify_bootimg_extra_footer_args=' 912 '--prop com.android.build.boot.os_version:13 ' 913 '--prop com.android.build.boot.security_patch:' 914 '2022-05-05\n') 915 gki_info_path = os.path.join(temp_out_dir, 'gki-info.txt') 916 with open(gki_info_path, 'w', encoding='utf-8') as f: 917 f.write(gki_info) 918 919 # Certifies the boot image with --gki_info. 920 boot_certified_img = os.path.join(temp_out_dir, 921 'boot-certified.img') 922 certify_bootimg_cmds = [ 923 'certify_bootimg', 924 '--boot_img', boot_img, 925 '--algorithm', 'SHA256_RSA4096', 926 '--key', './testdata/testkey_rsa4096.pem', 927 '--extra_args', '--prop gki:nice ' 928 '--prop space:"nice to meet you"', 929 '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' 930 '--prop avb_space:"nice to meet you"', 931 '--gki_info', gki_info_path, 932 '--output', boot_certified_img, 933 ] 934 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 935 936 # Checks an AVB footer exists and the image size remains. 937 self.assertTrue(has_avb_footer(boot_certified_img)) 938 self.assertEqual(os.path.getsize(boot_img), 939 os.path.getsize(boot_certified_img)) 940 941 # Checks the content in the AVB footer. 942 self._test_boot_signatures( 943 temp_out_dir, 944 {'boot-certified.img': self._EXPECTED_AVB_FOOTER_WITH_GKI_INFO}) 945 946 # Checks the content in the GKI certificate. 947 extract_boot_signatures(boot_certified_img, temp_out_dir) 948 self._test_boot_signatures( 949 temp_out_dir, 950 {'boot_signature1': 951 self._EXPECTED_BOOT_SIGNATURE_WITH_GKI_INFO, 952 'boot_signature2': 953 self._EXPECTED_KERNEL_SIGNATURE_WITH_GKI_INFO}) 954 955 def test_certify_bootimg_exceed_size(self): 956 """Tests the boot signature size exceeded max size of the signature.""" 957 with tempfile.TemporaryDirectory() as temp_out_dir: 958 boot_img = os.path.join(temp_out_dir, 'boot.img') 959 generate_test_boot_image(boot_img) 960 961 # Certifies the boot.img with many --extra_args, and checks 962 # it will raise the ValueError() exception. 963 boot_certified_img = os.path.join(temp_out_dir, 964 'boot-certified.img') 965 certify_bootimg_cmds = [ 966 'certify_bootimg', 967 '--boot_img', boot_img, 968 '--algorithm', 'SHA256_RSA2048', 969 '--key', './testdata/testkey_rsa2048.pem', 970 # Makes it exceed the signature max size. 971 '--extra_args', '--prop foo:bar --prop gki:nice ' * 128, 972 '--output', boot_certified_img, 973 ] 974 975 try: 976 subprocess.run(certify_bootimg_cmds, check=True, 977 capture_output=True, cwd=self._exec_dir, 978 encoding='utf-8') 979 self.fail('Exceeding signature size assertion is not raised') 980 except subprocess.CalledProcessError as err: 981 self.assertIn('ValueError: boot_signature size must be <= ', 982 err.stderr) 983 984 def test_certify_bootimg_archive(self): 985 """Tests certify_bootimg for a boot images archive..""" 986 with tempfile.TemporaryDirectory() as temp_out_dir: 987 boot_img_archive_name = os.path.join(temp_out_dir, 'boot-img') 988 gki_info = ('certify_bootimg_extra_args=' 989 '--prop KERNEL_RELEASE:5.10.42' 990 '-android13-0-00544-ged21d463f856 ' 991 '--prop BRANCH:android13-5.10-2022-05 ' 992 '--prop BUILD_NUMBER:ab8295296 ' 993 '--prop SPACE:"nice to meet you"\n' 994 'certify_bootimg_extra_footer_args=' 995 '--prop com.android.build.boot.os_version:13 ' 996 '--prop com.android.build.boot.security_patch:' 997 '2022-05-05\n') 998 boot_img_archive_path = generate_test_boot_image_archive( 999 boot_img_archive_name, 1000 'gztar', 1001 # A list of (boot_img_name, kernel_size, partition_size). 1002 [('boot.img', 8 * 1024, 128 * 1024), 1003 ('boot-lz4.img', 16 * 1024, 256 * 1024)], 1004 gki_info) 1005 1006 # Certify the boot image archive, with a RSA4096 key. 1007 boot_certified_img_archive = os.path.join( 1008 temp_out_dir, 'boot-certified-img.tar.gz') 1009 certify_bootimg_cmds = [ 1010 'certify_bootimg', 1011 '--boot_img_archive', boot_img_archive_path, 1012 '--algorithm', 'SHA256_RSA4096', 1013 '--key', './testdata/testkey_rsa4096.pem', 1014 '--extra_args', '--prop gki:nice ' 1015 '--prop space:"nice to meet you"', 1016 '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' 1017 '--prop avb_space:"nice to meet you"', 1018 '--output', boot_certified_img_archive, 1019 ] 1020 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 1021 1022 extract_boot_archive_with_signatures(boot_certified_img_archive, 1023 temp_out_dir) 1024 1025 # Checks an AVB footer exists and the image size remains. 1026 boot_img = os.path.join(temp_out_dir, 'boot.img') 1027 self.assertTrue(has_avb_footer(boot_img)) 1028 self.assertEqual(os.path.getsize(boot_img), 128 * 1024) 1029 1030 boot_lz4_img = os.path.join(temp_out_dir, 'boot-lz4.img') 1031 self.assertTrue(has_avb_footer(boot_lz4_img)) 1032 self.assertEqual(os.path.getsize(boot_lz4_img), 256 * 1024) 1033 1034 # Checks the content in the AVB footer. 1035 self._test_boot_signatures( 1036 temp_out_dir, 1037 {'boot.img': self._EXPECTED_AVB_FOOTER_BOOT, 1038 'boot-lz4.img': self._EXPECTED_AVB_FOOTER_BOOT_LZ4}) 1039 1040 # Checks the content in the GKI certificate. 1041 self._test_boot_signatures( 1042 temp_out_dir, 1043 {'boot/boot_signature1': 1044 self._EXPECTED_BOOT_SIGNATURE1_RSA4096, 1045 'boot/boot_signature2': 1046 self._EXPECTED_BOOT_SIGNATURE2_RSA4096, 1047 'boot-lz4/boot_signature1': 1048 self._EXPECTED_BOOT_LZ4_SIGNATURE1_RSA4096, 1049 'boot-lz4/boot_signature2': 1050 self._EXPECTED_BOOT_LZ4_SIGNATURE2_RSA4096}) 1051 1052 def test_certify_bootimg_archive_without_gki_info(self): 1053 """Tests certify_bootimg for a boot images archive.""" 1054 with tempfile.TemporaryDirectory() as temp_out_dir: 1055 boot_img_archive_name = os.path.join(temp_out_dir, 'boot-img') 1056 1057 # Checks ceritfy_bootimg works for a boot images archive without a 1058 # gki-info.txt. Using *.zip -> *.tar. 1059 boot_img_archive_path = generate_test_boot_image_archive( 1060 boot_img_archive_name, 1061 'zip', 1062 # A list of (boot_img_name, kernel_size, partition_size). 1063 [('boot-gz.img', 8 * 1024, 128 * 1024)], 1064 gki_info=None) 1065 # Certify the boot image archive, with a RSA4096 key. 1066 boot_certified_img_archive = os.path.join( 1067 temp_out_dir, 'boot-certified-img.tar') 1068 certify_bootimg_cmds = [ 1069 'certify_bootimg', 1070 '--boot_img_archive', boot_img_archive_path, 1071 '--algorithm', 'SHA256_RSA4096', 1072 '--key', './testdata/testkey_rsa4096.pem', 1073 '--extra_args', '--prop gki:nice ' 1074 '--prop space:"nice to meet you"', 1075 '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' 1076 '--prop avb_space:"nice to meet you"', 1077 '--output', boot_certified_img_archive, 1078 ] 1079 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 1080 1081 # Checks ceritfy_bootimg works for a boot images archive with a 1082 # special gki-info.txt. Using *.tar -> *.tgz. 1083 boot_img_archive_path = generate_test_boot_image_archive( 1084 boot_img_archive_name, 1085 'tar', 1086 # A list of (boot_img_name, kernel_size, partition_size). 1087 [('boot-gz.img', 8 * 1024, 128 * 1024)], 1088 gki_info='a=b\n' 1089 'c=d\n') 1090 # Certify the boot image archive, with a RSA4096 key. 1091 boot_certified_img_archive2 = os.path.join( 1092 temp_out_dir, 'boot-certified-img.tgz') 1093 certify_bootimg_cmds = [ 1094 'certify_bootimg', 1095 '--boot_img_archive', boot_img_archive_path, 1096 '--algorithm', 'SHA256_RSA4096', 1097 '--key', './testdata/testkey_rsa4096.pem', 1098 '--extra_args', '--prop gki:nice ' 1099 '--prop space:"nice to meet you"', 1100 '--extra_footer_args', '--salt a11ba11b --prop avb:nice ' 1101 '--prop avb_space:"nice to meet you"', 1102 '--output', boot_certified_img_archive2, 1103 ] 1104 subprocess.run(certify_bootimg_cmds, check=True, cwd=self._exec_dir) 1105 1106 extract_boot_archive_with_signatures(boot_certified_img_archive2, 1107 temp_out_dir) 1108 1109 # Checks an AVB footer exists and the image size remains. 1110 boot_3_img = os.path.join(temp_out_dir, 'boot-gz.img') 1111 self.assertTrue(has_avb_footer(boot_3_img)) 1112 self.assertEqual(os.path.getsize(boot_3_img), 128 * 1024) 1113 1114 # Checks the content in the AVB footer. 1115 self._test_boot_signatures( 1116 temp_out_dir, 1117 {'boot-gz.img': self._EXPECTED_AVB_FOOTER_BOOT_GZ}) 1118 1119 # Checks the content in the GKI certificate. 1120 self._test_boot_signatures( 1121 temp_out_dir, 1122 {'boot-gz/boot_signature1': 1123 self._EXPECTED_BOOT_GZ_SIGNATURE1_RSA4096, 1124 'boot-gz/boot_signature2': 1125 self._EXPECTED_BOOT_GZ_SIGNATURE2_RSA4096}) 1126 1127 1128# I don't know how, but we need both the logger configuration and verbosity 1129# level > 2 to make atest work. And yes this line needs to be at the very top 1130# level, not even in the "__main__" indentation block. 1131logging.basicConfig(stream=sys.stdout) 1132 1133if __name__ == '__main__': 1134 unittest.main(verbosity=2) 1135