Ejemplo n.º 1
0
def test_der_lengths(selenium):

    from cryptography.hazmat._der import OCTET_STRING, DERReader, encode_der

    for [length, header] in [
            # Single-byte lengths.
        (0, b"\x04\x00"),
        (1, b"\x04\x01"),
        (2, b"\x04\x02"),
        (127, b"\x04\x7f"),
            # Long-form lengths.
        (128, b"\x04\x81\x80"),
        (129, b"\x04\x81\x81"),
        (255, b"\x04\x81\xff"),
        (0x100, b"\x04\x82\x01\x00"),
        (0x101, b"\x04\x82\x01\x01"),
        (0xFFFF, b"\x04\x82\xff\xff"),
        (0x10000, b"\x04\x83\x01\x00\x00"),
    ]:
        body = length * b"a"
        der = header + body

        reader = DERReader(der)
        element = reader.read_element(OCTET_STRING)
        reader.check_empty()
        assert element.data.tobytes() == body

        assert encode_der(OCTET_STRING, body) == der
Ejemplo n.º 2
0
def test_der_lengths(length, header):
    body = length * b"a"
    der = header + body

    reader = DERReader(der)
    element = reader.read_element(OCTET_STRING)
    reader.check_empty()
    assert element.data.tobytes() == body

    assert encode_der(OCTET_STRING, body) == der
Ejemplo n.º 3
0
def _key_identifier_from_public_key(public_key):
    if isinstance(public_key, RSAPublicKey):
        data = public_key.public_bytes(
            serialization.Encoding.DER,
            serialization.PublicFormat.PKCS1,
        )
    elif isinstance(public_key, EllipticCurvePublicKey):
        data = public_key.public_bytes(
            serialization.Encoding.X962,
            serialization.PublicFormat.UncompressedPoint)
    else:
        # This is a very slow way to do this.
        serialized = public_key.public_bytes(
            serialization.Encoding.DER,
            serialization.PublicFormat.SubjectPublicKeyInfo)

        reader = DERReader(serialized)
        with reader.read_single_element(SEQUENCE) as public_key_info:
            algorithm = public_key_info.read_element(SEQUENCE)
            public_key = public_key_info.read_element(BIT_STRING)

        # Double-check the algorithm structure.
        with algorithm:
            algorithm.read_element(OBJECT_IDENTIFIER)
            if not algorithm.is_empty():
                # Skip the optional parameters field.
                algorithm.read_any_element()

        # BIT STRING contents begin with the number of padding bytes added. It
        # must be zero for SubjectPublicKeyInfo structures.
        if public_key.read_byte() != 0:
            raise ValueError('Invalid public key encoding')

        data = public_key.data

    return hashlib.sha1(data).digest()
Ejemplo n.º 4
0
    def parse(self, x509_obj):
        extensions = []
        seen_oids = set()
        for i in range(self.ext_count(x509_obj)):
            ext = self.get_ext(x509_obj, i)
            self._backend.openssl_assert(ext != self._backend._ffi.NULL)
            crit = self._backend._lib.X509_EXTENSION_get_critical(ext)
            critical = crit == 1
            oid = x509.ObjectIdentifier(
                _obj2txt(self._backend,
                         self._backend._lib.X509_EXTENSION_get_object(ext)))
            if oid in seen_oids:
                raise x509.DuplicateExtension(
                    "Duplicate {} extension found".format(oid), oid)

            # These OIDs are only supported in OpenSSL 1.1.0+ but we want
            # to support them in all versions of OpenSSL so we decode them
            # ourselves.
            if oid == ExtensionOID.TLS_FEATURE:
                # The extension contents are a SEQUENCE OF INTEGERs.
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                data_bytes = _asn1_string_to_bytes(self._backend, data)
                features = DERReader(data_bytes).read_single_element(SEQUENCE)
                parsed = []
                while not features.is_empty():
                    parsed.append(features.read_element(INTEGER).as_integer())
                # Map the features to their enum value.
                value = x509.TLSFeature(
                    [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed])
                extensions.append(x509.Extension(oid, critical, value))
                seen_oids.add(oid)
                continue
            elif oid == ExtensionOID.PRECERT_POISON:
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                # The contents of the extension must be an ASN.1 NULL.
                reader = DERReader(_asn1_string_to_bytes(self._backend, data))
                reader.read_single_element(NULL).check_empty()
                extensions.append(
                    x509.Extension(oid, critical, x509.PrecertPoison()))
                seen_oids.add(oid)
                continue

            try:
                handler = self.handlers[oid]
            except KeyError:
                # Dump the DER payload into an UnrecognizedExtension object
                data = self._backend._lib.X509_EXTENSION_get_data(ext)
                self._backend.openssl_assert(data != self._backend._ffi.NULL)
                der = self._backend._ffi.buffer(data.data, data.length)[:]
                unrecognized = x509.UnrecognizedExtension(oid, der)
                extensions.append(x509.Extension(oid, critical, unrecognized))
            else:
                ext_data = self._backend._lib.X509V3_EXT_d2i(ext)
                if ext_data == self._backend._ffi.NULL:
                    self._backend._consume_errors()
                    raise ValueError(
                        "The {} extension is invalid and can't be "
                        "parsed".format(oid))

                value = handler(self._backend, ext_data)
                extensions.append(x509.Extension(oid, critical, value))

            seen_oids.add(oid)

        return x509.Extensions(extensions)
Ejemplo n.º 5
0
def decode_dss_signature(signature):
    with DERReader(signature).read_single_element(SEQUENCE) as seq:
        r = seq.read_element(INTEGER).as_integer()
        s = seq.read_element(INTEGER).as_integer()
        return r, s
Ejemplo n.º 6
0
def test_der():
    # This input is the following structure, using
    # https://github.com/google/der-ascii
    #
    # SEQUENCE {
    #   SEQUENCE {
    #     NULL {}
    #     INTEGER { 42 }
    #     OCTET_STRING { "hello" }
    #   }
    # }
    der = b"\x30\x0e\x30\x0c\x05\x00\x02\x01\x2a\x04\x05\x68\x65\x6c\x6c\x6f"
    reader = DERReader(der)
    with pytest.raises(ValueError):
        reader.check_empty()

    with pytest.raises(ValueError):
        with reader:
            pass

    with pytest.raises(ZeroDivisionError):
        with DERReader(der):
            raise ZeroDivisionError

    # Parse the outer element.
    outer = reader.read_element(SEQUENCE)
    reader.check_empty()
    assert outer.data.tobytes() == der[2:]

    # Parse the outer element with read_any_element.
    reader = DERReader(der)
    tag, outer2 = reader.read_any_element()
    reader.check_empty()
    assert tag == SEQUENCE
    assert outer2.data.tobytes() == der[2:]

    # Parse the outer element with read_single_element.
    outer3 = DERReader(der).read_single_element(SEQUENCE)
    assert outer3.data.tobytes() == der[2:]

    # read_single_element rejects trailing data.
    with pytest.raises(ValueError):
        DERReader(der + der).read_single_element(SEQUENCE)

    # Continue parsing the structure.
    inner = outer.read_element(SEQUENCE)
    outer.check_empty()

    # Parsing a missing optional element should work.
    assert inner.read_optional_element(INTEGER) is None

    null = inner.read_element(NULL)
    null.check_empty()

    # Parsing a present optional element should work.
    integer = inner.read_optional_element(INTEGER)
    assert integer is not None
    assert integer.as_integer() == 42

    octet_string = inner.read_element(OCTET_STRING)
    assert octet_string.data.tobytes() == b"hello"

    # Parsing a missing optional element should work when the input is empty.
    inner.check_empty()
    assert inner.read_optional_element(INTEGER) is None

    # Re-encode the same structure.
    der2 = encode_der(
        SEQUENCE,
        encode_der(
            SEQUENCE,
            encode_der(NULL),
            encode_der(INTEGER, encode_der_integer(42)),
            encode_der(OCTET_STRING, b"hello"),
        ),
    )
    assert der2 == der
Ejemplo n.º 7
0
def test_invalid_integer(bad_input):
    reader = DERReader(bad_input)
    with pytest.raises(ValueError):
        reader.as_integer()
Ejemplo n.º 8
0
def test_integer(value, der):
    assert encode_der_integer(value) == der
    assert DERReader(der).as_integer() == value
Ejemplo n.º 9
0
def test_der_reader_basic():
    reader = DERReader(b"123456789")
    assert reader.read_byte() == ord(b"1")
    assert reader.read_bytes(1).tobytes() == b"2"
    assert reader.read_bytes(4).tobytes() == b"3456"

    with pytest.raises(ValueError):
        reader.read_bytes(4)

    assert reader.read_bytes(3).tobytes() == b"789"

    # The input is now empty.
    with pytest.raises(ValueError):
        reader.read_bytes(1)
    with pytest.raises(ValueError):
        reader.read_byte()
Ejemplo n.º 10
0
def test_der_reader_wrong_tag():
    reader = DERReader(b"\x04\x00")
    with pytest.raises(ValueError):
        reader.read_element(SEQUENCE)
Ejemplo n.º 11
0
def test_der_reader_bad_input(bad_input):
    reader = DERReader(bad_input)
    with pytest.raises(ValueError):
        reader.read_any_element()
Ejemplo n.º 12
0
def decode_dss_signature(signature: bytes) -> typing.Tuple[int, int]:
    with DERReader(signature).read_single_element(SEQUENCE) as seq:
        r = seq.read_element(INTEGER).as_integer()
        s = seq.read_element(INTEGER).as_integer()
        return r, s
Ejemplo n.º 13
0
def test_der_reader_basic(selenium):
    import pytest
    from cryptography.hazmat._der import DERReader

    reader = DERReader(b"123456789")
    assert reader.read_byte() == ord(b"1")
    assert reader.read_bytes(1).tobytes() == b"2"
    assert reader.read_bytes(4).tobytes() == b"3456"

    with pytest.raises(ValueError):
        reader.read_bytes(4)

    assert reader.read_bytes(3).tobytes() == b"789"

    # The input is now empty.
    with pytest.raises(ValueError):
        reader.read_bytes(1)
    with pytest.raises(ValueError):
        reader.read_byte()
Ejemplo n.º 14
0
  def parse(self, backend, x509_obj):
    extensions = []
    seen_oids = set()
    for i in range(self.ext_count(backend, x509_obj)):
      ext = self.get_ext(backend, x509_obj, i)
      backend.openssl_assert(ext != backend._ffi.NULL)
      crit = backend._lib.X509_EXTENSION_get_critical(ext)
      critical = crit == 1
      oid = x509.ObjectIdentifier(
        _obj2txt(backend, backend._lib.X509_EXTENSION_get_object(ext))        
      )
      if oid in seen_oids:
        raise x509.DuplicateExtension(
          "Duplicate {} extension found".format(oid), oid        
        )

      if oid == ExtensionOID.TLS_FEATURE:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        data_bytes = _asn1_string_to_bytes(backend, data)
        features = DERReader(data_bytes).read_single_element(SEQUENCE)
        parsed = []
        while not features.is_empty():
          parsed.append(features.read_element(INTEGER).as_integer())

        value = x509.TLSFeature(
          [_TLS_FEATURE_TYPE_TO_ENUM[x] for x in parsed]        
        )
        extensions.append(x509.Extension(oid, critical, value))
        seen_oids.add(oid)
        continue
      elif oid == ExtensionOID.PRECERT_POSION:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        reader = DERReader(_asn1_string_to_bytes(backend, data))
        reader.read_single_element(NULL).check_empty()
        extensions.append(x509.Extension(
          oid, critical, x509.PrecertPoison()    
        ))
        seen_oids.add(oid)
        continue
      elif oid == ExtensionOID.PRECERT_POISON:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        reader = DERReader(_asn1_string_to_bytes(backend, data))
        reader.read_single_element(NULL).check_empty()
        extensions.append(x509.Extension(
          oid, critical, x509.PrecertPoison()    
        ))
        seen_oids.add(oid)
        continue

      try:
        handler = self.handlers[oid]
      except KeyError:
        data = backend._lib.X509_EXTENSION_get_data(ext)
        backend.openssl_assert(data != backend._ffi.NULL)
        der = backend._ffi.buffer(data.data, data.length)[:]
        unrecognized = x509.UnrecognizedExtension(oid, der)
        extensions.append(
          x509.Extension(oid, critical, unrecognized)        
        )
      else:
        ext_data = backend._lib.X509V3_EXT_d2i(ext)
        if ext_data == backend._ffi.NULL:
          backend._consume_errors()
          raise ValueError(
            "The {} extension is invalid and can't be "
            "parsed".format(oid)
          )

        value = handler(backend, ext_data)
        extensions.append(x509.Extension(oid, critical, value))

      seen_oids.add(oid)

    return x509.Extensions(extenions)