示例#1
0
class AttributeExtractor(object):
    def __init__(self, cert_data=None, hash_segment_metadata=None):

        self.image_region = "Attestation Cert"

        self.attributes = SigningAttributes()

        if (cert_data, hash_segment_metadata) == (None, None):
            raise RuntimeError(
                "cert_data and hash_segment_data cannot both be None")

        if hash_segment_metadata is not None:
            self._init_using_hash_segment_and_cert(hash_segment_metadata,
                                                   cert_data)
            self.image_region = "Hash Segment/Attestation Cert"
        else:
            self._init_using_cert(cert_data)

    def _init_using_hash_segment_and_cert(self, hash_segment_metadata,
                                          cert_data):
        self.attributes.update_from_hash_segment_and_attest_cert(
            hash_segment_metadata, cert_data)

    def _init_using_cert(self, cert_data):
        self.attributes.update_from_attest_cert(cert_data)

    def __repr__(self):
        return str(self.attributes)
    def initialize(self, imageinfo):
        """ The following should be set at the end of the call

        self.certs[BaseSignerV2.ROOT].cert
        self.certs[BaseSignerV2.CA].cert
        self.certs[BaseSignerV2.ATTEST].cert
        self.signature
        """
        # Initialize the base signer
        BaseSignerV2.initialize(self, imageinfo)

        # Create the request packet
        attrs = SigningAttributes()
        attrs.update_from_image_info_attrs(self.signing_attributes)
        request = {
            'machine': platform.node(),
            'sign_id': imageinfo.sign_id,
            'to_sign': BinString(self.hash_to_sign),
            'authority': imageinfo.authority,
            'signing_attributes': self.get_general_properties_dict(imageinfo.general_properties),
        }

        # Send the signing request
        remote_host, remote_port = self.resolve_remote_server_info()
        client = QcomRemoteClient(host=remote_host, port=remote_port)
        logger.info('Signing with the remote server at ' + remote_host + ':' +
                    str(remote_port) + '. Please wait for signing to complete.')
        response = client.sign_hash(request=request)

        # Check return code
        if response['retcode'] != 0:
            raise RuntimeError('Qcom remote signing failed [' + str(response['retcode']) + ']: ' +
                               str(response['errstr']))

        # Set the local vars
        root_cert, ca_cert, attest_cert, signature = (str(response['sig_pkg']['root']), str(response['sig_pkg']['ca']),
                                                      str(response['sig_pkg']['attest']),
                                                      str(response['sig_pkg']['signature']))

        # Make sure all assets are present
        if signature is None:
            raise RuntimeError("Signature is missing")
        if attest_cert is None:
            raise RuntimeError("Attestation Certificate is missing")
        if ca_cert is None:
            raise RuntimeError("CA Certificate is missing")
        if root_cert is None:
            raise RuntimeError("Root Certificate is missing")

        # Set all the variables
        self.certs[self.ROOT].cert = cert.get_cert_in_format(root_cert, utils.FORMAT_DER, utils.FORMAT_PEM)
        self.certs[self.CA].cert = cert.get_cert_in_format(ca_cert, utils.FORMAT_DER, utils.FORMAT_PEM)
        self.certs[self.ATTEST].cert = cert.get_cert_in_format(attest_cert, utils.FORMAT_DER, utils.FORMAT_PEM)
        self.signature = signature
示例#3
0
 def validate_signing_attributes(self, cert_chain_der, imageinfo):
     if not cert_chain_der:
         raise RuntimeError(
             'Cert chain must contain at least 1 certificate.')
     attest_cert = cert_chain_der[0]
     attr_config = SigningAttributes()
     attr_config.update_from_image_info_attrs(imageinfo.signing_attributes)
     attr_attest = SigningAttributes()
     attr_attest.update_from_attest_cert(attest_cert)
     return attr_attest.compare(attr_config, attr_attest.EXCLUDE_NON_ATTEST)
示例#4
0
    def validate_hash_segment_metadata(self, authority=None):
        from sectools.common.utils.c_misc import create_mismatch_table
        # Validate metedata for unsigned image.
        # If image is signed, validation is done in signer.
        if not self.is_signed(authority):
            hash_segment_metadata = self.get_hash_segment_metadata(authority)
            if hash_segment_metadata is not None:
                from sectools.features.isc.signer.signerutils.attribute_extractor import AttributeExtractor
                from sectools.features.isc.signer.signerutils.attributes import SigningAttributes
                errstr = []
                extracted_image_attributes = AttributeExtractor(
                    hash_segment_metadata=hash_segment_metadata).attributes
                attr_config = SigningAttributes()
                attr_config.update_from_image_info_attrs(self.imageinfo)
                mismatches = extracted_image_attributes.compare(
                    attr_config,
                    extracted_image_attributes.EXCLUDE_HASH_SEGMENT_METADATA)
                create_mismatch_table(mismatches,
                                      errstr,
                                      operation="signing",
                                      data_type_to_compare="Attribute",
                                      image_region="Hash Segment")
                if errstr:
                    raise RuntimeError(
                        'Following validations failed for the image:\n       '
                        + '\n       '.join([(str(authority + 1) + '. ' + e)
                                            for authority, e in enumerate(
                                                errstr)]))

        # Ensure metadata sw_ids match
        hash_segment_metadata = self.get_hash_segment_metadata(
            defines.AUTHORITY_OEM)
        hash_segment_metadata_qti = self.get_hash_segment_metadata(
            defines.AUTHORITY_QTI)
        if hash_segment_metadata and hash_segment_metadata_qti and hash_segment_metadata[
                "sw_id"] != hash_segment_metadata_qti["sw_id"]:
            errstr = []
            mismatches = [('sw_id', [hex(hash_segment_metadata["sw_id"])],
                           [hex(hash_segment_metadata_qti["sw_id"])])]
            create_mismatch_table(mismatches,
                                  errstr,
                                  operation="signing",
                                  data_type_to_compare="Attribute",
                                  image_region="Metadata",
                                  image_region2="Metadata QTI")
            if errstr:
                raise RuntimeError(
                    'Following validations failed for the image:\n       ' +
                    '\n       '.join([(str(authority + 1) + '. ' + e)
                                      for authority, e in enumerate(errstr)]))
示例#5
0
    def __init__(self, cert_data=None, hash_segment_metadata=None):

        self.image_region = "Attestation Cert"

        self.attributes = SigningAttributes()

        if (cert_data, hash_segment_metadata) == (None, None):
            raise RuntimeError(
                "cert_data and hash_segment_data cannot both be None")

        if hash_segment_metadata is not None:
            self._init_using_hash_segment_and_cert(hash_segment_metadata,
                                                   cert_data)
            self.image_region = "Hash Segment/Attestation Cert"
        else:
            self._init_using_cert(cert_data)
    def update_tosign_data(cls, hash_to_sign, binary_to_sign, imageinfo, pf):
        pf.file_data['to_sign']['data'] = hash_to_sign
        signing_config = \
            {
                'binary_len': len(binary_to_sign),
                'sign_id': imageinfo.sign_id,
                'chipset': imageinfo.chipset,
            }

        # Check if signing attributes should be sent as well
        signer_attributes = imageinfo.config.signing.signer_attributes.remote_client_signer_attributes
        if signer_attributes and signer_attributes.send_signing_overrides:
            attrs = SigningAttributes()
            attrs.update_from_image_info_attrs(imageinfo.signing_attributes)
            signing_config['signing_attributes'] = attrs.get_json()

        pf.file_data['signing_config']['data'] = json.dumps(signing_config)
示例#7
0
def update_image_serial_bound_notes(authority, parsegen, imageinfo):

    if authority == AUTHORITY_QTI:
        cert_chain_der = cert.split_cert_chain_bin(
            parsegen._mbn_parsegen.cert_chain_qti)
    else:
        cert_chain_der = cert.split_cert_chain_bin(
            parsegen._mbn_parsegen.cert_chain)

    hash_segment_meta_data = parsegen.get_hash_segment_metadata(
        authority=authority)
    if not cert_chain_der and not hash_segment_meta_data:
        return

    image_signing_attributes = AttributeExtractor(
        cert_data=cert_chain_der[0] if cert_chain_der else None,
        hash_segment_metadata=hash_segment_meta_data,
        attributes=SigningAttributes()).attributes

    msm_part = None
    soc_hw_version = None
    soc_vers = image_signing_attributes.soc_vers
    in_use_soc_hw_version = image_signing_attributes.in_use_soc_hw_version
    if in_use_soc_hw_version:
        soc_hw_version = image_signing_attributes.hw_id[:-8]
    else:
        msm_part = image_signing_attributes.hw_id[:-8]
    platform_independent = False
    if (image_signing_attributes.metadata_major_version, image_signing_attributes.metadata_minor_version) == \
            (METADATA_MAJOR_VERSION_1, METADATA_MINOR_VERSION_0):
        if not image_signing_attributes.in_use_soc_hw_version and not image_signing_attributes.in_use_hw_id:
            platform_independent = True

    try:
        serial_binding_feature_set = serial_bound_feature_manager.get_feature_set(
            ChipsetProfile(parsegen.secboot_version, in_use_soc_hw_version,
                           msm_part, soc_vers, soc_hw_version,
                           platform_independent))
        serial_binding_feature_set.update_image_serial_bound_notes(
            image_signing_attributes,
            imageinfo.create_serial_bound_notes(authority))
    except RuntimeError:
        pass
    def sign_hash(self,
                  hash_to_sign,
                  imageinfo,
                  binary_to_sign=None,
                  debug_dir=None,
                  sha_algo=None,
                  binary_to_sign_len=None):
        # Find the hash_package
        packages_folder = imageinfo.dest_image.image_dir
        to_sign_package = Package(packages_folder,
                                  src.get_class_ToSignPackageFiles())

        try:
            if to_sign_package.package is None:
                raise RemoteSignerError(
                    'Please place the to_sign package in ' + packages_folder,
                    RemoteSignerError.E_PACKAGE_MISSING)

            # Read the hash package
            to_sign_package.update_data()
            to_sign, signing_config = src.use_tosign_data(to_sign_package.pf)
            signing_config = json.loads(signing_config)

            # Get the binary length
            binary_to_sign_len = int(signing_config['binary_len'])

            # Use the signing overrides
            signing_attributes = signing_config.get('signing_attributes', None)
            if signing_attributes is not None:
                signer_attributes = imageinfo.config.signing.signer_attributes.remote_signer_attributes
                if signer_attributes and signer_attributes.allow_signing_overrides:
                    sa = SigningAttributes()
                    sa.update_from_json(signing_attributes)
                    sa.update_image_info_attrs(imageinfo.signing_attributes)
                else:
                    raise RemoteSignerError(
                        'Signing attributes override is not accepted.',
                        RemoteSignerError.E_PACKAGE_MISSING)

        except RemoteSignerError:
            raise

        except RuntimeError as e:
            raise RemoteSignerError(e.message)

        # Sign using openssl locally
        signer_output = OpenSSLSigner.sign_hash(
            self,
            hash_to_sign,
            imageinfo,
            binary_to_sign=binary_to_sign,
            debug_dir=debug_dir,
            sha_algo=sha_algo,
            binary_to_sign_len=binary_to_sign_len)

        # Generate the signature package
        signature_package = Package(packages_folder,
                                    src.get_class_SignaturePackageFiles())
        src.update_signature_package(signer_output.signature,
                                     signer_output.attestation_cert,
                                     signer_output.attestation_ca_cert,
                                     [signer_output.root_cert],
                                     signature_package.pf)
        signature_package.package = src.get_signature_package_path(imageinfo)
        signature_package.save_package()

        return signer_output
示例#9
0
 def validate_signing_attributes(self, cert_chain_der, imageinfo, extracted_image_attributes):
     if not cert_chain_der:
         raise RuntimeError('Cert chain must contain at least 1 certificate.')
     attr_config = SigningAttributes()
     attr_config.update_from_image_info_attrs(imageinfo.signing_attributes)
     return extracted_image_attributes.compare(attr_config, extracted_image_attributes.EXCLUDE_NON_ATTEST)