implement support for encoding name constraints
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ace0467..4573a47 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,6 +9,8 @@
 * The :class:`~cryptography.x509.Certificate` class now has
   :attr:`~cryptography.x509.Certificate.signature` and
   :attr:`~cryptography.x509.Certificate.tbs_certificate_bytes` attributes.
+* :class:`~cryptography.x509.NameConstraints` are now supported in the
+  :class:`~cryptography.x509.CertificateBuilder`.
 
 1.1.1 - 2015-11-19
 ~~~~~~~~~~~~~~~~~~
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 8e163dc..51c8410 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -195,6 +195,7 @@
 
 NAME_CONSTRAINTS *NAME_CONSTRAINTS_new(void);
 void NAME_CONSTRAINTS_free(NAME_CONSTRAINTS *);
+int Cryptography_i2d_NAME_CONSTRAINTS(NAME_CONSTRAINTS *, unsigned char **);
 
 OTHERNAME *OTHERNAME_new(void);
 void OTHERNAME_free(OTHERNAME *);
@@ -277,6 +278,8 @@
 int sk_GENERAL_SUBTREE_push(Cryptography_STACK_OF_GENERAL_SUBTREE *,
                             GENERAL_SUBTREE *);
 
+GENERAL_SUBTREE *GENERAL_SUBTREE_new(void);
+
 void sk_ASN1_INTEGER_free(Cryptography_STACK_OF_ASN1_INTEGER *);
 int sk_ASN1_INTEGER_num(Cryptography_STACK_OF_ASN1_INTEGER *);
 ASN1_INTEGER *sk_ASN1_INTEGER_value(Cryptography_STACK_OF_ASN1_INTEGER *, int);
@@ -295,4 +298,13 @@
 """
 
 CUSTOMIZATIONS = """
+/* i2d_NAME_CONSTRAINTS doesn't exist, but this is the way the macros in
+   asn1t.h would implement it. We're not using those macros in case
+   OpenSSL exposes this function in the future. */
+int Cryptography_i2d_NAME_CONSTRAINTS(NAME_CONSTRAINTS *nc,
+                                      unsigned char **out) {
+    return ASN1_item_i2d((ASN1_VALUE *)nc, out,
+                         ASN1_ITEM_rptr(NAME_CONSTRAINTS));
+}
+
 """
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 8cf6755..9811e3b 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -58,6 +58,42 @@
 _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"])
 
 
+def _encode_name_constraints(backend, name_constraints):
+    nc = backend._lib.NAME_CONSTRAINTS_new()
+    assert nc != backend._ffi.NULL
+    nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free)
+    permitted = _encode_general_subtree(
+        backend, name_constraints.permitted_subtrees
+    )
+    nc.permittedSubtrees = permitted
+    excluded = _encode_general_subtree(
+        backend, name_constraints.excluded_subtrees
+    )
+    nc.excludedSubtrees = excluded
+
+    pp = backend._ffi.new('unsigned char **')
+    r = backend._lib.Cryptography_i2d_NAME_CONSTRAINTS(nc, pp)
+    assert r > 0
+    pp = backend._ffi.gc(
+        pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+    )
+    return pp, r
+
+
+def _encode_general_subtree(backend, subtrees):
+    if subtrees is None:
+        return backend._ffi.NULL
+    else:
+        general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null()
+        for name in subtrees:
+            gs = backend._lib.GENERAL_SUBTREE_new()
+            gs.base = _encode_general_name(backend, name)
+            res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs)
+            assert res >= 1
+
+        return general_subtrees
+
+
 def _encode_asn1_int(backend, x):
     """
     Converts a python integer to an ASN1_INTEGER. The returned ASN1_INTEGER
@@ -585,6 +621,7 @@
     ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_crl_distribution_points,
     ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy,
     ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck,
+    ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints,
 }
 
 
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 9b5dda6..5a1c4c5 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -2030,6 +2030,41 @@
 
     @pytest.mark.requires_backend_interface(interface=RSABackend)
     @pytest.mark.requires_backend_interface(interface=X509Backend)
+    def test_name_constraints(self, backend):
+        issuer_private_key = RSA_KEY_2048.private_key(backend)
+        subject_private_key = RSA_KEY_2048.private_key(backend)
+
+        not_valid_before = datetime.datetime(2002, 1, 1, 12, 1)
+        not_valid_after = datetime.datetime(2030, 12, 31, 8, 30)
+
+        excluded = [x509.DNSName(u"name.local")]
+        nc = x509.NameConstraints(
+            permitted_subtrees=None, excluded_subtrees=excluded
+        )
+
+        cert = x509.CertificateBuilder().subject_name(
+            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+        ).issuer_name(
+            x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, u'US')])
+        ).not_valid_before(
+            not_valid_before
+        ).not_valid_after(
+            not_valid_after
+        ).public_key(
+            subject_private_key.public_key()
+        ).serial_number(
+            123
+        ).add_extension(
+            nc, critical=False
+        ).sign(issuer_private_key, hashes.SHA256(), backend)
+
+        ext = cert.extensions.get_extension_for_oid(
+            ExtensionOID.NAME_CONSTRAINTS
+        )
+        assert ext.value == nc
+
+    @pytest.mark.requires_backend_interface(interface=RSABackend)
+    @pytest.mark.requires_backend_interface(interface=X509Backend)
     def test_key_usage(self, backend):
         issuer_private_key = RSA_KEY_2048.private_key(backend)
         subject_private_key = RSA_KEY_2048.private_key(backend)