Esempio n. 1
0
    def default_certificate_data(self,
                                 tool,
                                 target: Target,
                                 entrance_exam: EntranceExamMXS40v1,
                                 probe_id=None):
        """
        Gets a dictionary with the default values.
        Default certificate requires device to be connected to read
        device public key and die ID, which are used as a certificate
        fields
        :param tool: Programming tool to connect to device
        :param target: Target object
        :param entrance_exam: The object used to execute entrance exam
               before provisioning.
        :param probe_id: Probe ID. Need to be used if more than one
               device is connected to the computer.
        :return: Dictionary with the certificate fields.
        """
        # Read silicon data
        if tool.connect(target.name, probe_id=probe_id, ap='sysap'):
            VersionHelper.log_version(tool, target)
            VersionHelper.verify_sfb_version(tool, target)
            data = read_silicon_data(tool, target)
            if data is None:
                logger.error('Failed to read silicon data')
                return None

            dev_pub_key = target.key_reader.read_public_key(tool, KeyId.DEVICE)
            tool.disconnect()
            if dev_pub_key is None:
                return None
        else:
            logger.error('Failed to connect to device')
            return None

        # Get HSM private key
        hsm_priv_key, hsm_pub_key = target.policy_parser.hsm_private_key()

        # Get serial number
        silicon_data = SiliconDataParser(data)
        serial = int(silicon_data.get_serial())
        if serial <= 0:
            max_serial = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
            logger.warning(f'Serial number created from die ID is {serial}, '
                           f'setting serial number to maximum available value '
                           f'{max_serial}')
            serial = max_serial

        data = {
            'subject_name': 'Example Certificate',
            'country': 'US',
            'state': 'San Jose',
            'organization': 'Cypress Semiconductor',
            'issuer_name': 'Cypress Semiconductor',
            'public_key': dev_pub_key,
            'private_key': hsm_priv_key,
            'serial_number': serial,
        }
        logger.debug(json.dumps(data))
        return data
Esempio n. 2
0
 def read_public_key(self, key_id, key_fmt, out_file=None, probe_id=None):
     """
     Reads public key from device and saves it to the file
     :param key_id: Key ID to read
     :param key_fmt: Key format (jwk or pem)
     :param out_file: Filename where to save the key
     :param probe_id: Probe serial number
     :return: Key if it read successfully, otherwise None
     """
     key = None
     if self.tool.connect(self.target_name, probe_id=probe_id, ap='sysap'):
         VersionHelper.log_version(self.tool, self.target)
         VersionHelper.verify_sfb_version(self.tool, self.target)
         try:
             key = self.key_reader.read_public_key(self.tool, key_id,
                                                   key_fmt)
             if out_file:
                 out_file = os.path.abspath(out_file)
                 with open(out_file, 'w') as fp:
                     if key_fmt == 'jwk':
                         json.dump(key, fp, indent=4)
                     elif key_fmt == 'pem':
                         fp.write(key.decode("utf-8"))
                     else:
                         fp.write(str(key))
                 logger.info(f'Key saved: {out_file}')
             self.tool.disconnect()
         except (ValueError, FileNotFoundError) as e:
             logger.error(e)
     return key
Esempio n. 3
0
    def entrance_exam(self, probe_id=None, ap='cm4', erase_flash=False):
        """
        Checks device life-cycle, Flashboot firmware and Flash state.
        :param probe_id: Probe serial number.
        :param ap: The access port used for entrance exam
        :param erase_flash: Indicates whether to erase flash before the
               entrance exam
        :return True if the device is ready for provisioning,
                otherwise False.
        """
        if not self._validate_policy(['pre_build', 'dap_disabling']):
            return False

        status = False
        if self.tool.connect(self.target_name, probe_id=probe_id, ap=ap):
            VersionHelper.log_version(self.tool, self.target)
            if not VersionHelper.verify_sfb_version(self.tool, self.target):
                return False
            context = ProvisioningContext(self.target.provisioning_strategy)
            if erase_flash:
                context.erase_flash(self.tool, self.target)
            status = self.entr_exam.execute(self.tool)
            if status == EntranceExamStatus.FLASH_NOT_EMPTY:
                if self.skip_prompts:
                    logger.error('Entrance exam failed. '
                                 'User firmware running on chip detected')
                    return ProvisioningStatus.FAIL
                else:
                    answer = input(
                        'Erase user firmware running on chip? (y/n): ')
                    if answer.lower() == 'y':
                        context.erase_flash(self.tool, self.target)
            self.tool.disconnect()
        return status == EntranceExamStatus.OK
Esempio n. 4
0
    def re_provision_device(self,
                            probe_id=None,
                            ap='sysap',
                            erase_boot=False,
                            control_dap_cert=None,
                            skip_bootloader=False):
        """
        Executes device re-provisioning
        :param probe_id: Probe serial number.
        :param ap: The access port used for re-provisioning
        :param erase_boot: Indicates whether erase BOOT slot
        :param control_dap_cert: The certificate that provides the
               access to control DAP
        :param skip_bootloader: Indicates whether to skip bootloader
               programming during reprovisioning
        :return: Provisioning result. True if success, otherwise False.
        """
        if not self._validate_policy():
            return False

        # Get bootloader program file
        btldr = None
        if not skip_bootloader:
            btldr = self.bootloader_provider.hex_path()
            if not os.path.isfile(btldr):
                logger.error(f'Cannot find bootloader file \'{btldr}\'')
                return False

        context = ProvisioningContext(self.target.provisioning_strategy)

        if self.tool.connect(self.target_name, probe_id=probe_id, ap=ap):
            VersionHelper.log_version(self.tool, self.target)
            if not VersionHelper.verify_sfb_version(self.tool, self.target):
                return False
            status = context.re_provision(self.tool,
                                          self.target,
                                          btldr,
                                          erase_boot=erase_boot,
                                          control_dap_cert=control_dap_cert,
                                          ap=ap,
                                          probe_id=probe_id)
            self.tool.disconnect()
        else:
            status = ProvisioningStatus.FAIL

        if status == ProvisioningStatus.FAIL:
            logger.error('Error occurred while reprovisioning device')

        return status == ProvisioningStatus.OK
Esempio n. 5
0
 def read_die_id(self, probe_id=None, ap='sysap'):
     """
     Reads die ID
     :param probe_id: Probe serial number
     :param ap: The access port used to read the data
     :return: Die ID if success, otherwise None
     """
     die_id = None
     if self.tool.connect(self.target_name, probe_id=probe_id, ap=ap):
         VersionHelper.log_version(self.tool, self.target)
         VersionHelper.verify_sfb_version(self.tool, self.target)
         reader = self.target.silicon_data_reader(self.target)
         die_id = reader.read_die_id(self.tool)
         self.tool.disconnect()
     return die_id
Esempio n. 6
0
 def encrypted_programming(self, encrypted_image, probe_id=None):
     """
     Programs encrypted image.
     :param encrypted_image: The encrypted image to program.
     :param probe_id: Probe serial number.
     :return: True if the image programmed successfully, otherwise False.
     """
     result = False
     context = EncryptedProgrammingContext(AesHeaderStrategy)
     if self.tool.connect(self.target_name, probe_id=probe_id, ap='sysap'):
         VersionHelper.log_version(self.tool, self.target)
         VersionHelper.verify_sfb_version(self.tool, self.target)
         result = context.program(self.tool, self.target, encrypted_image)
         self.tool.disconnect()
     return result
Esempio n. 7
0
 def process():
     result = False
     try:
         if ctx.obj:
             if 'TOOL' not in ctx.obj:
                 return False
             ctx.obj['TOOL'].print_version(probe_id, ap)
         else:
             VersionHelper.print_version(target_names_by_type('family'))
         result = True
     except AssertionError:
         print_assertion_error()
     except Exception as e:
         logger.error(e)
         logger.debug(e, exc_info=True)
     return result
Esempio n. 8
0
    def print_version(self, probe_id=None, ap='sysap'):
        """
        Outputs CyBootloader version bundled with the package. If
        device is connected outputs CyBootloader and Secure Flash
        Boot version programmed into device
        :param probe_id: Probe serial number
        :param ap: The access port used for to read CyBootloader and
               Secure Flash Boot version from device
        """
        sfb_ver = 'unknown'
        connected = self.tool.connect(self.target_name,
                                      probe_id=probe_id,
                                      blocking=False,
                                      ap=ap)
        if connected:
            sfb_ver = VersionHelper.sfb_version(self.tool, self.target)
            bootloader_ver = VersionHelper.device_bootloader_version(
                self.tool, self.target)
            VersionHelper.verify_sfb_version(self.tool, self.target)
            self.tool.disconnect()

        VersionHelper.print_version([self.target_name])
        if connected:
            print('Device:')
            print(f'\tCyBootloader: {bootloader_ver}')
            print(f'\tSecure Flash Boot: {sfb_ver}')
Esempio n. 9
0
    def provision_device(self, probe_id=None, ap='cm4'):
        """
        Executes device provisioning - the process of creating device
        identity, attaching policy and bootloader.
        :param probe_id: Probe serial number.
        :param ap: The access port used for provisioning
        :return: Provisioning result. True if success, otherwise False.
        """
        if not self._validate_policy():
            return False

        # Get bootloader program file
        bootloader = self.bootloader_provider.hex_path()
        if not os.path.isfile(bootloader):
            logger.error(f'Cannot find bootloader file \'{bootloader}\'')
            return False

        context = ProvisioningContext(self.target.provisioning_strategy)

        if self.tool.connect(self.target_name, probe_id=probe_id, ap=ap):
            VersionHelper.log_version(self.tool, self.target)
            if not VersionHelper.verify_sfb_version(self.tool, self.target):
                return False
            status = context.provision(self.tool,
                                       self.target,
                                       self.entr_exam,
                                       bootloader,
                                       probe_id=probe_id,
                                       ap=ap,
                                       skip_prompts=self.skip_prompts)
            self.tool.disconnect()
        else:
            status = ProvisioningStatus.FAIL

        if status == ProvisioningStatus.FAIL:
            logger.error('Error occurred while provisioning device')
            return False

        return True
Esempio n. 10
0
    def encrypt_image(self,
                      image,
                      host_key_id: KeyId,
                      dev_key_id: KeyId,
                      algorithm='ECC',
                      key_length=16,
                      encrypted_image='encrypted_image.txt',
                      padding_value=0,
                      probe_id=None):
        """
        Creates encrypted image for encrypted programming.
        :param image: The image to encrypt.
        :param host_key_id: Host private key ID (4 - HSM, 5 - OEM).
        :param dev_key_id: Device public key ID (1 - device, 12 - group).
        :param algorithm: Asymmetric algorithm for key derivation function.
        :param key_length: Derived key length.
        :param encrypted_image: Output file of encrypted image for
               encrypted programming.
        :param padding_value: Value for image padding.
        :param probe_id: Probe serial number.
               Used to read device public key from device.
        """
        if not self._validate_policy(['dap_disabling']):
            return False

        # Get host private key
        logger.debug(f'Host key id = {host_key_id}')
        try:
            _, host_key_pem = self.policy_parser.get_private_key(host_key_id)
        except ValueError as ex:
            logger.error(ex)
            return False

        # Get public key
        pub_key_pem = None
        logger.debug(f'Device key id = {dev_key_id}')

        connected = self.tool.connect(self.target_name,
                                      probe_id=probe_id,
                                      blocking=False,
                                      ap='sysap')
        if connected:
            VersionHelper.log_version(self.tool, self.target)
            VersionHelper.verify_sfb_version(self.tool, self.target)
            logger.info('Read device public key from device')
            pub_key_pem = self.key_reader.read_public_key(
                self.tool, dev_key_id, 'pem')
            self.tool.disconnect()

        if not connected or not pub_key_pem:
            logger.info(f'Read public key {dev_key_id} from file')
            try:
                _, pub_key_pem = self.policy_parser.get_public_key(
                    dev_key_id, pre_build=True)
            except ValueError as ex:
                logger.error(ex)
                return False

        # Create AES key
        key_to_encrypt = get_aes_key(key_length)

        # Create encrypted image
        context = EncryptedProgrammingContext(AesHeaderStrategy)
        aes_header = context.create_header(host_key_pem, pub_key_pem,
                                           key_to_encrypt, algorithm,
                                           key_length)
        context.create_encrypted_image(image, key_to_encrypt, aes_header,
                                       host_key_id, dev_key_id,
                                       encrypted_image, padding_value)
        return True