Example #1
0
    def _parse_attributes(cls, data):
        """Given a set of Attributes, parses them and returns them as a dict

        :param data: The attributes to process
        """

        result = {}
        for attr in data:
            typ = asn1.oids.get(attr['type'])
            values = []
            for value in attr['values']:
                if not isinstance(typ, tuple):
                    # This should transparently handle when the data is encapsulated in an OctetString but we are
                    # not expecting an OctetString
                    try:
                        from pyasn1.type import univ
                        if not isinstance(type, univ.OctetString):
                            _, v = ber_decoder.decode(value, recursiveFlag=0)
                        else:
                            v = value
                        value = guarded_ber_decode(v, asn1_spec=typ())
                    except Exception:
                        value = guarded_ber_decode(value, asn1_spec=typ())
                values.append(value)
            result[typ] = values

        return result
Example #2
0
    def _parse_attributes(cls, data, required=()):
        """Given a set of Attributes, parses them and returns them as a dict

        :param data: The authenticatedAttributes or unauthenticatedAttributes to process
        :param required: A list of required attributes
        """

        if isinstance(data, rfc2315.Attributes):
            type_key, value_key = 'type', 'values'
        elif isinstance(
                data, (rfc5652.SignedAttributes, rfc5652.UnsignedAttributes)):
            type_key, value_key = 'attrType', 'attrValues'

        result = {}
        for attr in data:
            typ = asn1.oids.get(attr[type_key])
            values = []
            for value in attr[value_key]:
                if not isinstance(typ, tuple):
                    value = guarded_ber_decode(value, asn1_spec=typ())
                values.append(value)
            result[typ] = values

        if not all((x in result for x in required)):
            raise SignerInfoParseError(
                "Not all required attributes found. Required: %s; Found: %s" %
                ([_print_type(x)
                  for x in required], [_print_type(x) for x in result]))

        return result
Example #3
0
    def _parse(self):
        super()._parse()

        # - Retrieve object from SpcSpOpusInfo from the authenticated attributes (for normal signer)
        self.program_name = self.more_info = None
        if asn1.spc.SpcSpOpusInfo in self.authenticated_attributes:
            if len(self.authenticated_attributes[asn1.spc.SpcSpOpusInfo]) != 1:
                raise AuthenticodeParseError(
                    "Only one SpcSpOpusInfo expected in SignerInfo.authenticatedAttributes"
                )

            self.program_name = self.authenticated_attributes[
                asn1.spc.SpcSpOpusInfo][0]['programName'].to_python()
            self.more_info = self.authenticated_attributes[
                asn1.spc.SpcSpOpusInfo][0]['moreInfo'].to_python()

        # - Authenticode can be signed using a RFC-3161 timestamp, so we discover this possibility here
        if pkcs7.Countersignature in self.unauthenticated_attributes \
                and asn1.spc.SpcRfc3161Timestamp in self.unauthenticated_attributes:
            raise AuthenticodeParseError(
                "Countersignature and RFC-3161 timestamp present in "
                "SignerInfo.unauthenticatedAttributes")

        if asn1.spc.SpcRfc3161Timestamp in self.unauthenticated_attributes:
            if len(self.unauthenticated_attributes[
                    asn1.spc.SpcRfc3161Timestamp]) != 1:
                raise AuthenticodeParseError(
                    "Only one RFC-3161 timestamp expected in "
                    "SignerInfo.unauthenticatedAttributes")

            ts_data = self.unauthenticated_attributes[
                asn1.spc.SpcRfc3161Timestamp][0]
            content_type = asn1.oids.get(ts_data['contentType'])
            if content_type is not rfc2315.SignedData:
                raise AuthenticodeParseError(
                    "RFC-3161 Timestamp does not contain SignedData structure")
            # Note that we expect rfc5652 compatible data here
            # This is a work-around for incorrectly tagged v2AttrCerts in the BER-encoded blob,
            # see the docstring for patch_rfc5652_signeddata for more details
            try:
                signed_data = guarded_ber_decode(
                    ts_data['content'], asn1_spec=rfc5652.SignedData())
            except ParseError:
                with patch_rfc5652_signeddata() as asn1_spec:
                    signed_data = guarded_ber_decode(ts_data['content'],
                                                     asn1_spec=asn1_spec)
            self.countersigner = RFC3161SignedData(signed_data)
Example #4
0
    def from_envelope(cls, data, *args, **kwargs):
        """Loads a :class:`SignedData` object from raw data that contains ContentInfo.

        :param bytes data: The bytes to parse
        """
        # This one is not guarded, which is intentional
        content, rest = ber_decoder.decode(data,
                                           asn1Spec=rfc2315.ContentInfo())
        if asn1.oids.get(content['contentType']) is not rfc2315.SignedData:
            raise ParseError("ContentInfo does not contain SignedData")

        data = guarded_ber_decode(content['content'],
                                  asn1_spec=rfc2315.SignedData())

        signed_data = cls(data, *args, **kwargs)
        signed_data._rest_data = rest
        return signed_data
Example #5
0
    def from_stl_file(cls, path=AUTHROOTSTL_PATH):
        with open(str(path), "rb") as f:
            content, rest = ber_decoder.decode(f.read(),
                                               asn1Spec=rfc2315.ContentInfo())
        #
        # from pyasn1 import debug
        # debug.setLogger(debug.Debug('all'))

        if asn1.oids.get(content['contentType']) is not rfc2315.SignedData:
            raise CertificateTrustListParseError(
                "ContentInfo does not contain SignedData")

        data = guarded_ber_decode(content['content'],
                                  asn1_spec=rfc2315.SignedData())

        signed_data = cls(data)
        signed_data._rest_data = rest
        return signed_data
Example #6
0
    def _parse(self):
        # Parse the fields of the SignedData structure
        if self.data['version'] != 1:
            raise AuthenticodeParseError(
                "SignedData.version must be 1, not %d" % self.data['version'])

        # digestAlgorithms
        if len(self.data['digestAlgorithms']) != 1:
            raise AuthenticodeParseError(
                "SignedData.digestAlgorithms must contain exactly 1 algorithm, not %d"
                % len(self.data['digestAlgorithms']))
        self.digest_algorithm = _get_digest_algorithm(
            self.data['digestAlgorithms'][0], "SignedData.digestAlgorithm")

        # SpcIndirectDataContent
        self.content_type = asn1.oids.get(
            self.data['contentInfo']['contentType'])
        if self.content_type is not asn1.spc.SpcIndirectDataContent:
            raise AuthenticodeParseError(
                "SignedData.contentInfo does not contain SpcIndirectDataContent"
            )
        spc_info = guarded_ber_decode(
            self.data['contentInfo']['content'],
            asn1_spec=asn1.spc.SpcIndirectDataContent())
        self.spc_info = SpcInfo(spc_info)

        # Certificates
        self.certificates = CertificateStore(
            [Certificate(cert) for cert in self.data['certificates']])

        # signerInfos
        if len(self.data['signerInfos']) != 1:
            raise AuthenticodeParseError(
                "SignedData.signerInfos must contain exactly 1 signer, not %d"
                % len(self.data['signerInfos']))

        self.signer_info = AuthenticodeSignerInfo(self.data['signerInfos'][0])

        # CRLs
        if 'crls' in self.data and self.data['crls'].isValue:
            raise AuthenticodeParseError(
                "SignedData.crls is present, but that is unexpected.")
Example #7
0
    def _parse(self):
        # digestAlgorithms
        if len(self.data['digestAlgorithms']) != 1:
            raise ParseError(
                "SignedData.digestAlgorithms must contain exactly 1 algorithm, not %d"
                % len(self.data['digestAlgorithms']))
        self.digest_algorithm = _get_digest_algorithm(
            self.data['digestAlgorithms'][0], "SignedData.digestAlgorithm")

        # contentType
        if isinstance(self.data, rfc2315.SignedData):
            self.content_type = asn1.oids.get(
                self.data['contentInfo']['contentType'])
            content = self.data['contentInfo']['content']
        elif isinstance(self.data, rfc5652.SignedData):
            self.content_type = asn1.oids.get(
                self.data['encapContentInfo']['eContentType'])
            content = self.data['encapContentInfo']['eContent']
        else:
            raise ParseError("Unknown SignedData data type {}".format(
                _print_type(self.data)))

        if self.content_type is not self._expected_content_type:
            raise ParseError("SignedData.contentInfo does not contain %s" %
                             _print_type(self._expected_content_type))

        # Content
        self.content = guarded_ber_decode(
            content, asn1_spec=self._expected_content_type())

        # Certificates
        self.certificates = CertificateStore([
            Certificate(cert) for cert in self.data['certificates']
            if Certificate.is_certificate(cert)
        ])

        # SignerInfo
        if self._signerinfo_class is not None:
            self.signer_infos = [
                self._signerinfo_class(si, parent=self)
                for si in self.data['signerInfos']
            ]
Example #8
0
def _verify_empty_algorithm_parameters(algorithm, location):
    if 'parameters' in algorithm and algorithm['parameters'].isValue:
        parameters = guarded_ber_decode(algorithm['parameters'])
        if not isinstance(parameters, univ.Null):
            raise ParseError("%s has parameters set, which is unexpected" %
                             (location, ))
Example #9
0
 def test_normal_read(self):
     self.assertTrue(guarded_ber_decode(univ.Any("\x01\x01\xff")))  # true
     self.assertFalse(guarded_ber_decode(univ.Any("\x01\x01\x00")))  # false
     self.assertIsInstance(guarded_ber_decode(univ.Any("\x05\x00")),
                           univ.Null)  # null