add policy constraints class
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 8bb3f40..14fc37c 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -1860,6 +1860,40 @@
 
         :type: int
 
+.. class:: PolicyConstraints
+
+    .. versionadded:: 1.3
+
+    The policy constraints extension can be used in certificates issued
+    to CAs.  The policy constraints extension constrains path validation
+    in two ways.  It can be used to prohibit policy mapping or require
+    that each certificate in a path contain an acceptable policy
+    identifier. For more information about the use of this extension see
+    :rfc:`5280`.
+
+    .. attribute:: require_explicit_policy
+
+        :type: int or None
+
+        If this field is present, the value indicates the number of additional
+        certificates that may appear in the path before an explicit policy is
+        required for the entire path. When an explicit policy is required, it
+        is necessary for all certificates in the path to contain an acceptable
+        policy identifier in the certificate policies extension.  An
+        acceptable policy identifier is the identifier of a policy required
+        by the user of the certification path or the identifier of a policy
+        that has been declared equivalent through policy mapping.
+
+    .. attribute:: inhibit_policy_mapping
+
+        :type: int or None
+
+        If this field is present, the value indicates the number of additional
+        certificates that may appear in the path before policy mapping is no
+        longer permitted.  For example, a value of one indicates that policy
+        mapping may be processed in certificates issued by the subject of this
+        certificate, but not in additional certificates in the path.
+
 .. class:: CRLNumber(crl_number)
 
     .. versionadded:: 1.2
@@ -2392,6 +2426,12 @@
         the ``CRLNumber`` extension type. This extension only has meaning
         for certificate revocation lists.
 
+    .. attribute:: POLICY_CONSTRAINTS
+
+        Corresponds to the dotted string ``"2.5.29.36"``. The identifier for the
+        :class:`PolicyConstraints` extension type.
+
+
 .. class:: CRLEntryExtensionOID
 
     .. versionadded:: 1.2
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index db55789..ba9cb37 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -490,6 +490,60 @@
 
 
 @utils.register_interface(ExtensionType)
+class PolicyConstraints(object):
+    def __init__(self, require_explicit_policy, inhibit_policy_mapping):
+        if require_explicit_policy is not None and not isinstance(
+            require_explicit_policy, six.integer_types
+        ):
+            raise TypeError(
+                "require_explicit_policy must be a non-negative integer or "
+                "None"
+            )
+
+        if inhibit_policy_mapping is not None and not isinstance(
+            inhibit_policy_mapping, six.integer_types
+        ):
+            raise TypeError(
+                "inhibit_policy_mapping must be a non-negative integer or None"
+            )
+
+        if inhibit_policy_mapping is None and require_explicit_policy is None:
+            raise ValueError(
+                "At least one of require_explicit_policy and "
+                "inhibit_policy_mapping must not be None"
+            )
+
+        self._require_explicit_policy = require_explicit_policy
+        self._inhibit_policy_mapping = inhibit_policy_mapping
+
+    def __repr__(self):
+        return (
+            u"<PolicyConstraints(require_explicit_policy={0.require_explicit"
+            u"_policy}, inhibit_policy_mapping={0.inhibit_policy_"
+            u"mapping})>".format(self)
+        )
+
+    def __eq__(self, other):
+        if not isinstance(other, PolicyConstraints):
+            return NotImplemented
+
+        return (
+            self.require_explicit_policy == other.require_explicit_policy and
+            self.inhibit_policy_mapping == other.inhibit_policy_mapping
+        )
+
+    def __ne__(self, other):
+        return not self == other
+
+    require_explicit_policy = utils.read_only_property(
+        "_require_explicit_policy"
+    )
+    inhibit_policy_mapping = utils.read_only_property(
+        "_inhibit_policy_mapping"
+    )
+
+
+@utils.register_interface(ExtensionType)
 class CertificatePolicies(object):
     oid = ExtensionOID.CERTIFICATE_POLICIES
 
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index d8a5f9d..ceb11df 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -2245,6 +2245,41 @@
         assert hash(ad) != hash(ad3)
 
 
+class TestPolicyConstraints(object):
+    def test_invalid_explicit_policy(self):
+        with pytest.raises(TypeError):
+            x509.PolicyConstraints("invalid", None)
+
+    def test_invalid_inhibit_policy(self):
+        with pytest.raises(TypeError):
+            x509.PolicyConstraints(None, "invalid")
+
+    def test_both_none(self):
+        with pytest.raises(ValueError):
+            x509.PolicyConstraints(None, None)
+
+    def test_repr(self):
+        pc = x509.PolicyConstraints(0, None)
+
+        assert repr(pc) == (
+            u"<PolicyConstraints(require_explicit_policy=0, inhibit_policy_ma"
+            u"pping=None)>"
+        )
+
+    def test_eq(self):
+        pc = x509.PolicyConstraints(2, 1)
+        pc2 = x509.PolicyConstraints(2, 1)
+        assert pc == pc2
+
+    def test_ne(self):
+        pc = x509.PolicyConstraints(2, 1)
+        pc2 = x509.PolicyConstraints(2, 2)
+        pc3 = x509.PolicyConstraints(3, 1)
+        assert pc != pc2
+        assert pc != pc3
+        assert pc != object()
+
+
 class TestAuthorityInformationAccess(object):
     def test_invalid_descriptions(self):
         with pytest.raises(TypeError):