Ejemplo n.º 1
0
    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")
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
 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)
Ejemplo n.º 10
0
 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
Ejemplo n.º 11
0
 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
Ejemplo n.º 12
0
 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]])
Ejemplo n.º 13
0
    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