Home | History | Annotate | Download | only in platform_DMVerityBitCorruption
      1 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import os
      7 import struct
      8 from autotest_lib.client.common_lib import error, utils
      9 from autotest_lib.client.cros import verity_utils
     10 
     11 class platform_DMVerityBitCorruption(verity_utils.VerityImageTest):
     12     version = 1
     13 
     14     _adjustment = 0
     15     _mask = 0x80
     16 
     17     def mod_tweak_block(self, run_count, backing_path, block_size,
     18                             block_count):
     19         logging.info('mod_tweak_block(%d, %s, %d, %d)' % (
     20                      run_count, backing_path, block_size, block_count))
     21         run_count = run_count % block_count
     22         with open(backing_path, 'r+b') as dev:
     23             dev.seek(run_count * block_size + self._adjustment)
     24             (byte,) = struct.unpack('B', dev.read(1))  # Get raw byte value.
     25             dev.seek(run_count * block_size + self._adjustment)
     26             dev.write(struct.pack('B', byte ^ self._mask))
     27 
     28 
     29     def mod_tweak_hash_block(self, run_count, backing_path, block_size,
     30                              block_count):
     31         logging.info('mod_tweak_hash_block(%d, %s, %d, %d)' % (
     32                      run_count, backing_path, block_size, block_count))
     33         with open(backing_path, 'r+b') as dev:
     34             # move to the start of the appropriate hash block
     35             dev.seek(block_count * block_size, os.SEEK_SET)
     36             dev.seek(run_count * block_size + self._adjustment, os.SEEK_CUR)
     37             (byte,) = struct.unpack('B', dev.read(1))
     38             # return to the start of the appropriate hash block
     39             dev.seek(block_count * block_size, os.SEEK_SET)
     40             dev.seek(run_count * block_size + self._adjustment, os.SEEK_CUR)
     41             dev.write(struct.pack('B', byte ^ self._mask))
     42 
     43 
     44     def run_once(self, bit_loc='first'):
     45         if bit_loc == 'first':
     46             pass
     47         elif bit_loc == 'last':
     48             self._adjustment = verity_utils.BLOCK_SIZE - 1
     49             self._mask = 0x01
     50         elif bit_loc == 'middle':
     51             self._adjustment = verity_utils.BLOCK_SIZE/2
     52         else:
     53             raise error.TestError('bit_loc must be first, last, or middle')
     54 
     55         # Corrupt the |bit_loc| bit of each block (on a per-block basis).
     56         self.mod_and_test(self.mod_tweak_block, self.image_blocks, False)
     57 
     58         # Repeat except on each block in the hash tree data.
     59         hash_blocks = (os.path.getsize(self.verity.hash_file) /
     60                        verity_utils.BLOCK_SIZE)
     61         self.mod_and_test(self.mod_tweak_hash_block, hash_blocks, False)
     62