Ejemplo n.º 1
0
    def read_sfb_version(self, tool):
        jwt_text = Crypto.read_jwt(self.entrance_exam_jwt)
        json_data = Crypto.readable_jwt(jwt_text)
        payload = json_data['payload']
        major_version = None
        minor_version = None
        for item in payload['ahb_reads']:
            if item['description'].startswith('SFB_VER_HI'):
                address = int(item['address'], 0)
                mask = int(item['mask'], 0)
                sfb_ver_hi = tool.read32(address)
                major_version = sfb_ver_hi & mask
            if item['description'].startswith('SFB_VER_LO'):
                address = int(item['address'], 0)
                mask = int(item['mask'], 0)
                sfb_ver_lo = tool.read32(address)
                minor_version = sfb_ver_lo & mask
            if major_version and minor_version:
                break

        # Parse SFB version values
        maj_version = (sfb_ver_hi >> 24) & 0x0F
        min_version = (sfb_ver_hi >> 16) & 0xFF
        patch = sfb_ver_lo >> 24
        build = sfb_ver_lo & 0x0000FFFF

        return f'{maj_version}.{min_version}.{patch}.{build}'
Ejemplo n.º 2
0
    def pack_provision_cmd(self, **kwargs):
        payload = {}
        if kwargs is not None:
            for k, v in kwargs.items():
                if type(v) is tuple:
                    sequence = []
                    for cert_file in v:
                        try:
                            with open(cert_file) as cert:
                                sequence.append(cert.read())
                            barr = bytearray(sequence[0], encoding='utf-8')
                            try:
                                x509.load_pem_x509_certificate(
                                    barr, default_backend())
                            except ValueError as ex:
                                raise ValueError(
                                    f'{ex} Invalid certificate \'{cert_file}\''
                                )
                        except UnicodeDecodeError:
                            sequence.append(self.der_to_pem(cert_file))
                    payload[k] = sequence
                else:
                    if os.path.isfile(v):
                        payload[k] = Crypto.read_jwt(v)
                    else:
                        payload[k] = v

        payload['type'] = Types.HSM_PROV_CMD

        hsm_priv_key = self.state['hsm_priv_key']
        prov_cmd = Crypto.create_jwt(payload, hsm_priv_key)

        return prov_cmd
Ejemplo n.º 3
0
 def get_cypress_public_key(self):
     """
     Gets Cypress public key from cy_auth JWT packet.
     :return: Cypress public key (JWK).
     """
     jwt_text = Crypto.read_jwt(self.policy_parser.get_cy_auth())
     json_data = Crypto.readable_jwt(jwt_text)
     return json_data["payload"]['cy_pub_key']
Ejemplo n.º 4
0
def readable_jwt(jwt):
    """
    Convert a JWT token in base64url into a readable dictionary object
    with decoded payload and header for printing and logging
    :param jwt: JWT filename
    :return: Readable dictionary
    """
    txt = Crypto.read_jwt(jwt) if os.path.isfile(jwt) else jwt
    readable = Crypto.readable_jwt(txt)
    return readable
Ejemplo n.º 5
0
    def create_device_identity(self, cy_auth, rot_auth, prod_id, grp_priv_key,
                               dev_priv_key, hsm_priv_key):
        """
        Creates prov_identity JWT packet
        :param cy_auth: cy_auth packet
        :param rot_auth: Root of trust authentication packet
        :param prod_id: Product ID
        :param grp_priv_key: Group private key
        :param dev_priv_key: Device private key
        :param hsm_priv_key: HSM private key for JWT creation
        :return: Tuple with readable prov_identity and prov_identity JWT
        """
        # Create device keys if not exist
        if dev_priv_key:
            if isinstance(dev_priv_key, dict):
                self.state['dev_priv_key'] = dev_priv_key
            else:
                if os.path.isfile(dev_priv_key):
                    self.state['dev_priv_key'] = Crypto.read_json(dev_priv_key)
                else:
                    self.state['dev_priv_key'], self.state['dev_pub_key'] = Crypto.create_jwk()
                    Crypto.dump_json(self.state['dev_priv_key'], dev_priv_key)

        # Create group keys if not exist
        if grp_priv_key:
            if isinstance(grp_priv_key, dict):
                self.state['grp_priv_key'] = grp_priv_key
            else:
                if os.path.isfile(grp_priv_key):
                    self.state['grp_priv_key'] = Crypto.read_json(grp_priv_key)
                else:
                    self.state['grp_priv_key'], self.state['grp_pub_key'] = Crypto.create_jwk()
                    Crypto.dump_json(self.state['grp_priv_key'], grp_priv_key)

        # Create prov_identity JWT
        payload = dict()
        payload['create_identity'] = True
        if 'dev_priv_key' in self.state:
            payload['dev_priv_key'] = self.state['dev_priv_key']
        if 'grp_priv_key' in self.state:
            payload['grp_priv_key'] = self.state['grp_priv_key']
        payload['cy_auth'] = cy_auth
        payload['rot_auth'] = rot_auth
        payload['prod_id'] = self.state['prod_id'] = prod_id

        self.state['create_identity'] = payload['create_identity']
        self.state['cy_auth'] = cy_auth
        payload['type'] = Types.HSM_PROV_CMD

        prov_identity = Crypto.create_jwt(payload, hsm_priv_key)
        return payload, prov_identity
Ejemplo n.º 6
0
    def create_provision_request(self, blob):
        """
        The OEM can create a request for provisioning by signing a keys & policies blob with its private key
        Note that blob must contain at least the prod_id field
        """
        # create the request
        oem_priv_key = self.state["oem_priv_key"]
        prov_req = Crypto.create_jwt(blob, oem_priv_key)

        # create audit record
        record = {}
        record["type"] = Types.OEM_PROV_REQ
        record["iat"] = datetime.now().isoformat(' ')
        record["prod_id"] = blob["prod_id"]
        record["prov_req"] = Crypto.readable_jwt(prov_req)
        self.append_audit_record(record)

        return prov_req
Ejemplo n.º 7
0
 def create_entity(self, hsm_priv_key=None, hsm_pub_key=None):
     """
     Creates the HSM entity.
     Creates the hsm_priv_key,hsm_pub_key key-pair.
     """
     if not hsm_priv_key and not hsm_pub_key:
         hsm_priv_key, hsm_pub_key = Crypto.create_jwk()
     self.state["hsm_priv_key"] = hsm_priv_key
     self.state["hsm_pub_key"] = hsm_pub_key
Ejemplo n.º 8
0
 def create_entity(self, chain_of_trust=[]):
     """
     Creates the Oem entity.
     Creates the Oem main key-pair and returns nothing.
     """
     oem_priv_key, oem_pub_key = Crypto.create_jwk()
     self.state["oem_priv_key"] = oem_priv_key
     self.state["oem_pub_key"] = oem_pub_key
     self.state["oem_chain_of_trust"] = chain_of_trust
Ejemplo n.º 9
0
 def create_entity(self, kid):
     """
     Creates the Customer entity.
     Creates the Customer main key-pair and returns nothing.
     """
     customer_priv_key, customer_pub_key = Crypto.create_jwk()
     customer_priv_key["kid"] = str(kid)
     customer_pub_key["kid"] = str(kid)
     self.state["custom_priv_key"] = customer_priv_key
     self.state["custom_pub_key"] = customer_pub_key
     self.state_loaded = True
Ejemplo n.º 10
0
    def pack_rot_auth(self, prod_id, hsm_pub_key):
        oem_pub_key = self.state["oem_pub_key"]
        oem_priv_key = self.state["oem_priv_key"]

        payload = dict()
        payload["type"] = Types.OEM_ROT_AUTH
        payload["oem_pub_key"] = oem_pub_key
        payload["hsm_pub_key"] = hsm_pub_key
        payload["prod_id"] = prod_id
        rot_auth = Crypto.create_jwt(payload, oem_priv_key)

        return rot_auth
Ejemplo n.º 11
0
    def pack_rot_auth(self, prod_id, hsm_pub_key):
        oem_pub_key = self.state["oem_pub_key"]
        oem_priv_key = self.state["oem_priv_key"]

        payload = {}
        payload["type"] = Types.OEM_ROT_AUTH
        payload["oem_pub_key"] = oem_pub_key
        payload["hsm_pub_key"] = hsm_pub_key
        payload["prod_id"] = prod_id
        payload["iat"] = int(datetime.now().timestamp())
        rot_auth = Crypto.create_jwt(payload, oem_priv_key)

        return rot_auth
Ejemplo n.º 12
0
def read_cm0_permissions(tool, reg_map):
    logger.info('Checking cm0 AP permissions')
    passed, data = get_prov_details(tool, reg_map, FB_POLICY_JWT)
    if passed and len(data) > 0:
        policy = Crypto.readable_jwt(data)
        silicon_policy_parser = PolicyParser(policy['payload'])
        cm0_open = silicon_policy_parser.is_cmx_ap_enabled(True)
        logger.info(f'cm0 AP {"open" if cm0_open else "closed"}')
    else:
        logger.error('Failed to read policy from device while getting AP '
                     'permission')
        logger.warning('Flash operations will be skipped')
        cm0_open = False
    return cm0_open
Ejemplo n.º 13
0
    def read_device_info(self, tool):
        jwt_text = Crypto.read_jwt(self.entrance_exam_jwt)
        json_data = Crypto.readable_jwt(jwt_text)
        payload = json_data['payload']
        silicon_id = None
        silicon_rev = None
        family_id = None
        for item in payload['ahb_reads']:
            if item['description'].startswith('SI_ID'):
                address = int(item['address'], 0)
                silicon_id = tool.read32(address) >> 16 & 0xFFFF
                silicon_rev = tool.read32(address) >> 8 & 0xFF
            if item['description'].startswith('FAMILY_ID'):
                address = int(item['address'], 0)
                mask = int(item['mask'], 0)
                family_id = tool.read32(address) & mask
            if silicon_id and silicon_rev and family_id:
                break

        DeviceInfo = namedtuple('DeviceInfo',
                                'silicon_id silicon_rev family_id')
        dev_info = DeviceInfo(silicon_id, silicon_rev, family_id)
        return dev_info
Ejemplo n.º 14
0
 def create_entity(self,
                   chain_of_trust=None,
                   oem_priv_key=None,
                   oem_pub_key=None):
     """
     Creates the Oem entity.
     Creates the Oem main key-pair and returns nothing.
     """
     if chain_of_trust is None:
         chain_of_trust = []
     if not oem_priv_key and not oem_pub_key:
         oem_priv_key, oem_pub_key = Crypto.create_jwk()
     self.state["oem_priv_key"] = oem_priv_key
     self.state["oem_pub_key"] = oem_pub_key
     self.state["oem_chain_of_trust"] = chain_of_trust
Ejemplo n.º 15
0
 def group_priv_key_packet(self, grp_priv_key):
     payload = {'grp_priv_key': grp_priv_key, 'type': 'OEM_GRP_PRIV_KEY'}
     jwt = Crypto.create_jwt(payload, self.state["oem_priv_key"])
     return jwt
Ejemplo n.º 16
0
 def data(self):
     if self._data is None:
         self._data = Crypto.readable_jwt(self.jwt)
     return self._data
Ejemplo n.º 17
0
    def execute(self, tool):
        """
        Checks device life-cycle, Flashboot firmware, Flash state and
        bunch of registers.
        """
        jwt_text = Crypto.read_jwt(self.entrance_exam_jwt)

        logger.info('*****************************************')
        logger.info('             ENTRANCE EXAM               ')
        logger.info('*****************************************')

        reader = self.target.silicon_data_reader(self.target)
        complete = reader.read_complete_status(tool)
        exam_pass = not complete
        if not exam_pass:
            logger.error('Device has been previously provisioned')

        if exam_pass:
            voltage = self.voltage_tool.get_voltage(tool=tool)
            v_min = self.voltage_tool.voltage_level * 0.9
            v_max = self.voltage_tool.voltage_level * 1.1
            if voltage < v_min or voltage > v_max:
                exam_pass = False
                logger.error(
                    f'Silicon voltage is out of range. Expected voltage '
                    f'level is in range {v_min} V - {v_max} V\n')
            else:
                exam_pass = True
            tool.set_ap(AP.SYS)

        # Verify entrance exam JWT signature
        if exam_pass:
            logger.info('Verify entrance exam JWT signature:')
            cy_pub_key = self.target.key_reader.get_cypress_public_key()
            exam_pass = Crypto.validate_jwt(jwt_text, cy_pub_key)
            if exam_pass:
                logger.info('Signature verified')
            else:
                logger.error('Invalid signature')

        # Verify ahb_reads32
        if exam_pass:
            json_data = Crypto.readable_jwt(jwt_text)
            payload = json_data['payload']
            tool.reset()
            exam_pass = self.verify_ahb_reads(tool, payload['ahb_reads'], 32)

        # Verify ahb_reads8
        if exam_pass:
            exam_pass &= self.verify_ahb_reads(tool, payload['ahb_reads8'], 8)

        # Verify region_hashes
        if exam_pass:
            for item in payload['region_hashes']:
                logger.info('.' * 70)
                logger.info(f'Verify {item["description"]}')
                logger.info('.' * 70)
                logger.info(f'Address: {item["address"]}')
                logger.info(f'Size:    {item["size"]}')
                logger.info(f'Mode:    {item["hash_id"]}')
                logger.info(f'Value:   {item["value"]}')
                syscall_status = region_hash(tool, self.reg_map)
                if syscall_status == RegionHashStatus.OK:
                    logger.info('PASS\n')
                else:
                    logger.info('FAIL\n')

        result = EntranceExamStatus.OK
        if exam_pass:
            if syscall_status == RegionHashStatus.FLASH_NOT_EMPTY:
                result = EntranceExamStatus.FLASH_NOT_EMPTY
            elif syscall_status == RegionHashStatus.FAIL:
                result = EntranceExamStatus.FAIL
        else:
            result = EntranceExamStatus.FAIL

        logger.info('*****************************************')
        if result == EntranceExamStatus.OK:
            logger.info('       ENTRANCE EXAM PASSED')
        else:
            logger.info('       ENTRANCE EXAM FAILED')
        logger.info('*****************************************')

        return result
Ejemplo n.º 18
0
 def __init__(self, jwt=None):
     self._jwt = jwt
     self._data = Crypto.readable_jwt(jwt) if jwt is not None else None
Ejemplo n.º 19
0
    def create_rot_authorization(self, signing_pkg):
        """
        OEM creates a root-of-trust authorization package based on the signing key package from the HSM
        It's a JWT with two main parts:
        - a rot_auth authorization token that is sent to the device
        - a chain of X509 certificates that establishses the OEM's trust in the HSM signing key
          Note that this chain is not used inside the device and used only by 3rd parties
        """
        oem_pub_key = self.state["oem_pub_key"]
        oem_priv_key = self.state["oem_priv_key"]
        oem_chain_of_trust = self.state["oem_chain_of_trust"]

        # get HSM public key and check CY authorization
        signing_pkg_payload = Crypto.jwt_payload(signing_pkg)
        cy_auth = signing_pkg_payload["cy_auth"]
        cy_auth_payload = Crypto.jwt_payload(cy_auth)
        cy_pub_key = cy_auth_payload["cy_pub_key"]
        hsm_pub_key = cy_auth_payload["hsm_pub_key"]
        if not Crypto.validate_jwt(cy_auth, cy_pub_key):
            raise Exception(
                "Invalid signature on Cypress HSM authorization in request")
        if cy_auth_payload["type"] != Types.CY_AUTH_HSM:
            raise Exception(
                "Invalid type for Cypress HSM authorization in request")
        if datetime.fromtimestamp(cy_auth_payload["exp"]) < datetime.now():
            raise Exception("Cypress HSM authorization expired")

        # validate HSM request itself
        signing_pub_key = signing_pkg_payload["signing_pub_key"]
        prod_id = signing_pkg_payload["prod_id"]
        if not Crypto.validate_jwt(signing_pkg, hsm_pub_key):
            raise Exception("Invalid signature on HSM signing key package")
        if signing_pkg_payload["type"] != Types.HSM_SIGNING_KEY_PKG:
            raise Exception("Invalid type on HSM signing key package")
        if datetime.fromtimestamp(signing_pkg_payload["exp"]) < datetime.now():
            raise Exception("HSM signing key package expired")

        # create the RoT transfer authorization (that will go to the device)
        payload = {}
        payload["type"] = Types.OEM_ROT_AUTH
        payload["oem_pub_key"] = oem_pub_key
        payload["hsm_pub_key"] = hsm_pub_key
        payload["prod_id"] = prod_id
        payload["iat"] = int(datetime.now().timestamp())
        rot_auth = Crypto.create_jwt(payload, oem_priv_key)

        # create the chain of trust
        cert = Crypto.create_x509_cert(signing_pub_key, oem_priv_key, prod_id)
        chain_of_trust = oem_chain_of_trust + [cert]

        # create the response
        exp = datetime.now() + timedelta(7)
        payload = {}
        payload["type"] = Types.OEM_ROT_AUTH_PKG
        payload["iat"] = int(datetime.now().timestamp())
        payload["exp"] = int(exp.timestamp())
        payload["prod_id"] = prod_id
        payload["rot_auth"] = rot_auth
        payload["chain_of_trust"] = chain_of_trust
        rot_auth_pkg = Crypto.create_jwt(payload, oem_priv_key)

        # create audit record
        signing_pkg_readable = Crypto.readable_jwt(signing_pkg)
        signing_pkg_readable["payload"]["cy_auth"] = Crypto.readable_jwt(
            signing_pkg_readable["payload"]["cy_auth"])
        signing_pkg_readable["payload"]["disti_auth"] = Crypto.readable_jwt(
            signing_pkg_readable["payload"]["disti_auth"])
        rot_auth_pkg_readable = Crypto.readable_jwt(rot_auth_pkg)
        rot_auth_pkg_readable["payload"]["rot_auth"] = Crypto.readable_jwt(
            rot_auth_pkg_readable["payload"]["rot_auth"])
        record = {}
        record["type"] = Types.OEM_ROT_AUTH_PKG
        record["iat"] = datetime.now().isoformat(' ')
        record["signing_pkg"] = signing_pkg_readable
        record["rot_auth_pkg"] = rot_auth_pkg_readable
        self.append_audit_record(record)

        return rot_auth_pkg