def __init__(self, args): self.args = args self.database = database.FAMILY_LIST["PAC_CARD"] log.debug(args.main_command) self.bitstream_type = self.database.SUPPORTED_TYPES[ args.main_command].ENUM self.verify = True if args.root_bitstream else False if self.verify: offset = 0 self.reh = common_util.BYTE_ARRAY("FILE", args.root_bitstream) con_type = self.reh.get_dword(offset + 8) if (self.reh.get_dword(offset) != database.DESCRIPTOR_BLOCK_MAGIC_NUM or self.reh.get_dword(offset + 4) != 128 or (con_type >> 8) & 0xFF != database.BITSTREAM_TYPE_RK_256 or self.reh.get_dword(offset + 128) != database.SIGNATURE_BLOCK_MAGIC_NUM): common_util.assert_in_error( False, "File '{}' is not a root entry hash programming bitstream". format(args.root_bitstream), ) if con_type & 0xFF != self.bitstream_type: log.warn("File '{}' different type than bitstream." " Validation impossible".format(args.root_bitstream)) self.verify = False if self.verify: self.val_root_hash = int.from_bytes(self.reh.data[1024:1056], byteorder="big") self.val_root_hash_dc = int.from_bytes(self.reh.data[1072:1104], byteorder="big")
def _find_openssl_so(self, version, *paths): candidates = list(paths) crypto = util.find_library('crypto') if crypto: candidates.insert(0, crypto) for c in candidates: dll = CDLL(c) if dll is None: log.warn('could not open: %s', c) continue try: dll.OpenSSL_version.argtypes = [c_int] dll.OpenSSL_version.restype = c_char_p except AttributeError: log.debug('"%s: does not have OpenSSL_version', c) continue c_version = dll.OpenSSL_version(0).decode("utf-8") m = OPENSSL_VERSION_RE.match(c_version) if m is None: log.warn('"%s" is not a valid OpenSSL version', c_version) continue if m.group('version') == version: return dll log.debug('OpenSSL version "%s" is not equal to "%s"', c_version, version)
def sign(self, sha, key): private_key = self.get_private_key(key) data = common_util.BYTE_ARRAY() private_key.sign(sha, data) log.debug("Signature len={}".format(data.size())) log.debug("".join("{:02x} ".format(x) for x in data.data)) return data
def sign(self, sha, key): try: key_, _ = self.get_key(key, ObjectClass.PRIVATE_KEY) except pkcs11.NoSuchKey: log.error("No such key") except pkcs11.MultipleObjectsReturned: log.error("multiple") rs = common_util.BYTE_ARRAY() rs.append_data(key_.sign(sha, mechanism=Mechanism.ECDSA)) log.debug("RS length is {}".format(rs.size())) log.debug("".join("{:02x} ".format(x) for x in rs.data)) return rs
def retrive_key_info(self): assert self.key is not None assert self.curve_info is None # Checking support type group = self.openssl.lib.EC_KEY_get0_group(self.key) common_util.assert_in_error( group is not None, "generate_openssl_key() failed to EC_KEY_get0_group()") type = self.openssl.lib.EC_GROUP_get_curve_name(group) self.curve_info = openssl.get_curve_info_from_enum(type) common_util.assert_in_error( self.curve_info is not None, "EC curve enum (%d) name (%s) is not supported" % (type, self.openssl.lib.OBJ_nid2ln(type)), ) log.debug("Curve info={}, group={}, type={}".format( self.curve_info, group, self.openssl.lib.OBJ_nid2ln(type))) # Get XY pub = self.openssl.lib.EC_KEY_get0_public_key(self.key) x = self.openssl.lib.BN_new() y = self.openssl.lib.BN_new() common_util.assert_in_error( self.openssl.lib.EC_POINT_get_affine_coordinates_GFp( group, pub, x, y, None), "Fail to EC_POINT_get_affine_coordinates_GFp()", ) temp = common_util.get_byte_size(self.openssl.lib.BN_num_bits(x)) common_util.assert_in_error( self.curve_info.size >= temp, ("Public key X size (%d Bytes) does not aligned " + "with EC curve (%d Bytes)") % (temp, self.curve_info.size), ) temp = common_util.get_byte_size(self.openssl.lib.BN_num_bits(y)) common_util.assert_in_error( self.curve_info.size >= temp, ("Public key Y size (%d Bytes) does not aligned " + "with EC curve (%d Bytes)") % (temp, self.curve_info.size), ) # Copy X and Y cpointer = self.get_char_point_from_bignum(x, self.curve_info.size) self.xy.append_data(cpointer.data) log.debug("".join("{:02x} ".format(x) for x in self.xy.data)) del cpointer cpointer = self.get_char_point_from_bignum(y, self.curve_info.size) self.xy.append_data(cpointer.data) log.debug("".join("{:02x} ".format(x) for x in self.xy.data)) del cpointer log.debug(self.xy) self.openssl.lib.BN_clear_free(x) self.openssl.lib.BN_clear_free(y)
def sign(self, sha, data, fixed_RS_size=0): log.debug("Sign: sha_size:{}".format(len(sha))) common_util.assert_in_error( len(sha) == 32 or len(sha) == 48 or len(sha) == 64, ("Supported SHA is SHA256, SHA314 and SHA512, " + "but found sha size of %d") % (len(sha) * 8), ) signature = self.openssl.lib.ECDSA_do_sign(sha, len(sha), self.key) common_util.assert_in_error( self.openssl.lib.ECDSA_do_verify(sha, len(sha), signature, self.key), "Fail to verify after the signing", ) r = c_void_p(None) s = c_void_p(None) self.openssl.lib.ECDSA_SIG_get0(signature, byref(r), byref(s)) # assign r cpointer = self.get_char_point_from_bignum(r, self.curve_info.size) log.debug("Sign: curve_info.size={}, cpointer.size={}".format( self.curve_info.size, cpointer.size())) data.append_data(cpointer.data) del cpointer if fixed_RS_size: assert fixed_RS_size == 48 or fixed_RS_size == 64 for _ in range(self.curve_info.size, fixed_RS_size): data.append_byte(0) # assign s cpointer = self.get_char_point_from_bignum(s, self.curve_info.size) data.append_data(cpointer.data) del cpointer if fixed_RS_size: assert fixed_RS_size == 48 or fixed_RS_size == 64 for _ in range(self.curve_info.size, fixed_RS_size): data.append_byte(0) # Free signature self.openssl.lib.ECDSA_SIG_free(signature)
def __init__(self, xy, key_info): self.xy = common_util.BYTE_ARRAY() self.xy.append_data(xy) log.debug("Got key info") log.debug("".join("{:02x} ".format(x) for x in self.xy.data)) log.debug(self.xy) self.key_info = key_info
def __init__(self, args, b0, b1, payload, json_str=None): super(print_bitstream, self).__init__(args) try: _ = payload[0] except TypeError: payload = payload.data self.cert_type = self.database.SUPPORTED_CERT_TYPES[args.cert_type] val = b0.get_dword(0) log.debug("platform value is '{}' ".format(hex(val))) type = b0.get_word(int(0xC)) self.dc_pr = val == database.DC_PLATFORM_NUM and type == database.PR_IDENTIFIER if not self.dc_pr: self.b0 = Block_0(b0.data, payload) self.b1 = Block_1(b1.data, self.b0) else: self.b0 = Block_0_dc(b0.data, payload) self.b1 = Block_1_dc(b1.data, self.b0) self.print_json(json_str) self.b0.print_block() self.b1.print_block() self.print_payload(self.b0, payload)
def __init__(self, file, openssl, key_info): self.key_info = key_info if isinstance(file, str): super(_PUBLIC_KEY, self).__init__(file, openssl, key_info) public_pem = self.check_pem_file() if public_pem: self.key = self.openssl.read_public_key(self.file) else: self.key = self.openssl.read_private_key(self.file) else: super(_PUBLIC_KEY, self).__init__("", openssl) self.key = file self.retrive_key_info() log.debug("Got key info") log.debug("".join("{:02x} ".format(x) for x in self.xy.data)) log.debug(self.xy)
def is_Darby_PR(self, contents, offset): # TODO: Write function to read dword and determine RC or VC val = contents.get_dword(offset) log.debug("platform value is '{}' ".format(hex(val))) type = contents.get_word(offset + int(0xC)) return val == database.DC_PLATFORM_NUM and type == database.PR_IDENTIFIER
def skip_JSON(self, contents): leng = contents.get_dword(GUID_LEN) log.debug("length of json={}".format(leng)) return leng + GUID_LEN + SIZEOF_LEN_FIELD
def is_JSON(self, contents): log.debug("GUID: {} vs. file {}".format( METADATA_GUID, "".join([chr(i) for i in contents.data[:GUID_LEN]]))) return METADATA_GUID == "".join( [chr(i) for i in contents.data[:GUID_LEN]])
def run(self, fname, file_offset, block0, block1, payload): log.info("Starting verification") payload_content = common_util.BYTE_ARRAY("FILE", fname) # Skip JSON and old signature if they exist has_json = self.is_JSON(payload_content) log.debug("has_json = {}".format(has_json)) sig_offset = 0 if not has_json else self.skip_JSON(payload_content) # Determine if platform is RC or DC self.dc_pr = self.is_Darby_PR(payload_content, sig_offset) fd = open(fname, "rb") fd.seek(file_offset, 0) b0 = fd.read(block0.size()) b1 = fd.read(block1.size()) if self.dc_pr: pay = fd.read(len(payload)) pay_good = pay == bytes(payload) else: pay = fd.read(payload.size()) pay_good = pay == bytes(payload.data) fd.close() common_util.assert_in_error( b0 == bytes(block0.data) and b1 == bytes(block1.data) and pay_good, "File not written properly", ) log.info("Bitstream file written properly (bits match expected)") pay_sha256_v = int.from_bytes(sha256(pay).digest(), byteorder="big") pay_sha384_v = int.from_bytes(sha384(pay).digest(), byteorder="big") if not self.dc_pr: if pay_sha256_v != int.from_bytes(b0[16:16 + 32], byteorder="big"): log.error("SHA-256 in Block 0 does not match") if pay_sha384_v != int.from_bytes(b0[48:48 + 48], byteorder="big"): log.error("SHA-384 in Block 0 does not match") # Check root hash if self.dc_pr: hash = int.from_bytes(sha256(b1[152:152 + 64]).digest(), byteorder="big") good = hash == self.val_root_hash_dc else: hash = int.from_bytes(sha256(b1[20:148]).digest(), byteorder="big") good = hash == self.val_root_hash if good: log.info("Root hash matches") else: log.error("Root hash mismatch:") log.error("Signed bitstream: {}".format( hex(hash))) log.error("Root entry hash bitstream provided: {}".format( hex(self.val_root_hash_dc if self.dc_pr else self.val_root_hash ))) if self.dc_pr: root_pub_key_x = int.from_bytes(b1[152:152 + 32], byteorder="big") root_pub_key_y = int.from_bytes(b1[152 + 32:152 + 64], byteorder="big") root_pub_key_v = (root_pub_key_x, root_pub_key_y) csk_pub_key_x = int.from_bytes(b1[264:264 + 32], byteorder="big") csk_pub_key_y = int.from_bytes(b1[264 + 32:264 + 64], byteorder="big") csk_pub_key_v = (csk_pub_key_x, csk_pub_key_y) csk_rs_r = int.from_bytes(b1[344:344 + 32], byteorder="big") csk_rs_s = int.from_bytes(b1[344 + 32:344 + 64], byteorder="big") csk_rs_v = (csk_rs_r, csk_rs_s) b0e_rs_r = int.from_bytes(b1[448:448 + 32], byteorder="big") b0e_rs_s = int.from_bytes(b1[448 + 32:448 + 64], byteorder="big") b0e_rs_v = (b0e_rs_r, b0e_rs_s) root_sha_v = hash csk_sha_v = int.from_bytes(sha256(b1[240:240 + 88]).digest(), byteorder="big") b0_sha_v = int.from_bytes(sha256(b0).digest(), byteorder="big") else: if self.cert_type == database.BITSTREAM_TYPE_CANCEL: b0e_off = 156 csk_pub_key_v = (0, 0) csk_rs_v = (0, 0) csk_sha_v = 0 else: b0e_off = 388 csk_pub_key_x = int.from_bytes(b1[164:164 + 32], byteorder="big") csk_pub_key_y = int.from_bytes(b1[212:212 + 32], byteorder="big") csk_pub_key_v = (csk_pub_key_x, csk_pub_key_y) csk_rs_r = int.from_bytes(b1[284:284 + 32], byteorder="big") csk_rs_s = int.from_bytes(b1[332:332 + 32], byteorder="big") csk_rs_v = (csk_rs_r, csk_rs_s) csk_sha_v = int.from_bytes(sha256(b1[152:152 + 128]).digest(), byteorder="big") root_pub_key_x = int.from_bytes(b1[32:32 + 32], byteorder="big") root_pub_key_y = int.from_bytes(b1[80:80 + 32], byteorder="big") root_pub_key_v = (root_pub_key_x, root_pub_key_y) b0e_rs_r = int.from_bytes(b1[b0e_off:b0e_off + 32], byteorder="big") b0e_rs_s = int.from_bytes(b1[b0e_off + 48:b0e_off + 48 + 32], byteorder="big") b0e_rs_v = (b0e_rs_r, b0e_rs_s) root_sha_v = hash b0_sha_v = int.from_bytes(sha256(b0).digest(), byteorder="big") # validate signatures if self.cert_type != database.BITSTREAM_TYPE_CANCEL: if ecdsa.verify_signature(root_pub_key_v, csk_sha_v, csk_rs_v): log.info("Signature of CSK with root key OK") else: log.error("Signature of CSK with root key mismatch") if ecdsa.verify_signature(csk_pub_key_v, b0_sha_v, b0e_rs_v): log.info("Signature of Block 0 with CSK OK") else: log.error("Signature of Block 0 with CSK mismatch") else: if ecdsa.verify_signature(root_pub_key_v, b0_sha_v, b0e_rs_v): log.info("Signature of Block 0 with root key OK") else: log.error("Signature of Block 0 with root key mismatch") return