1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/python3 2*6777b538SAndroid Build Coastguard Worker 3*6777b538SAndroid Build Coastguard Worker# Copyright 2022 The Chromium Authors. All rights reserved. 4*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 5*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file. 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Workerimport hashlib 8*6777b538SAndroid Build Coastguard Workerimport itertools 9*6777b538SAndroid Build Coastguard Workerimport sys 10*6777b538SAndroid Build Coastguard Worker 11*6777b538SAndroid Build Coastguard WorkerPAGE_SIZE = 0x1000 # System page size. 12*6777b538SAndroid Build Coastguard WorkerHASH_SIZE = 8 # Size of the hash in bytes. 13*6777b538SAndroid Build Coastguard Worker 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Workerdef hash_pages(data): 16*6777b538SAndroid Build Coastguard Worker out = bytearray() 17*6777b538SAndroid Build Coastguard Worker 18*6777b538SAndroid Build Coastguard Worker offset = 0 19*6777b538SAndroid Build Coastguard Worker while offset < len(data): 20*6777b538SAndroid Build Coastguard Worker # Extract a page and pad it with zeroes in case it's not a full page. 21*6777b538SAndroid Build Coastguard Worker # This is to emulate the behavior of mmap in Linux (and thus ChromeOS) 22*6777b538SAndroid Build Coastguard Worker # environments. 23*6777b538SAndroid Build Coastguard Worker # 24*6777b538SAndroid Build Coastguard Worker # "POSIX specifies that the system shall always zero fill any 25*6777b538SAndroid Build Coastguard Worker # partial page at the end of the object [...]". 26*6777b538SAndroid Build Coastguard Worker # 27*6777b538SAndroid Build Coastguard Worker # Reference: https://man7.org/linux/man-pages/man2/mmap.2.html 28*6777b538SAndroid Build Coastguard Worker page = bytearray(data[offset : offset + PAGE_SIZE]) 29*6777b538SAndroid Build Coastguard Worker page.extend(itertools.repeat(0x00, PAGE_SIZE - len(page))) 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker # Calculate the hash of the page. 32*6777b538SAndroid Build Coastguard Worker digest = hashlib.blake2b(page, digest_size=HASH_SIZE).digest() 33*6777b538SAndroid Build Coastguard Worker out.extend(digest) 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Worker offset += PAGE_SIZE 36*6777b538SAndroid Build Coastguard Worker 37*6777b538SAndroid Build Coastguard Worker return out 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Worker 40*6777b538SAndroid Build Coastguard Workerif __name__ == "__main__": 41*6777b538SAndroid Build Coastguard Worker # Check arguments. 42*6777b538SAndroid Build Coastguard Worker if len(sys.argv) != 3: 43*6777b538SAndroid Build Coastguard Worker error_str = "icuhash: wrong number of arguments\n\n" 44*6777b538SAndroid Build Coastguard Worker help_str = "usage: icuhash <infilename> <outfilename>\n\n" 45*6777b538SAndroid Build Coastguard Worker sys.exit(error_str + help_str) 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Worker # Extract arguments. 48*6777b538SAndroid Build Coastguard Worker in_filename = sys.argv[1] 49*6777b538SAndroid Build Coastguard Worker out_filename = sys.argv[2] 50*6777b538SAndroid Build Coastguard Worker 51*6777b538SAndroid Build Coastguard Worker # Read the input file. 52*6777b538SAndroid Build Coastguard Worker with open(in_filename, "rb") as in_file: 53*6777b538SAndroid Build Coastguard Worker data = in_file.read() 54*6777b538SAndroid Build Coastguard Worker # Calculate hashes for each page of the file. 55*6777b538SAndroid Build Coastguard Worker out_data = hash_pages(data) 56*6777b538SAndroid Build Coastguard Worker # Write the output file. 57*6777b538SAndroid Build Coastguard Worker with open(out_filename, "wb") as out_file: 58*6777b538SAndroid Build Coastguard Worker out_file.write(out_data) 59