Initial code to encode SANs
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index c18708c..5210c7c 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -42,7 +42,7 @@
 typedef struct asn1_string_st ASN1_IA5STRING;
 typedef ... ASN1_BIT_STRING;
 typedef ... ASN1_OBJECT;
-typedef ... ASN1_STRING;
+typedef struct asn1_string_st ASN1_STRING;
 typedef ... ASN1_TYPE;
 typedef ... ASN1_GENERALIZEDTIME;
 typedef ... ASN1_ENUMERATED;
@@ -87,6 +87,9 @@
 void ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *);
 int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *, const unsigned char *, int);
 
+/* ASN1 IA5STRING */
+ASN1_IA5STRING *ASN1_IA5STRING_new(void);
+
 /*  ASN1 INTEGER */
 ASN1_INTEGER *ASN1_INTEGER_new(void);
 void ASN1_INTEGER_free(ASN1_INTEGER *);
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 166fa59..36d9091 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -172,7 +172,9 @@
 int X509V3_EXT_add_alias(int, int);
 void X509V3_set_ctx(X509V3_CTX *, X509 *, X509 *, X509_REQ *, X509_CRL *, int);
 X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *);
+GENERAL_NAME *GENERAL_NAME_new(void);
 int GENERAL_NAME_print(BIO *, GENERAL_NAME *);
+GENERAL_NAMES *GENERAL_NAMES_new(void);
 void GENERAL_NAMES_free(GENERAL_NAMES *);
 void *X509V3_EXT_d2i(X509_EXTENSION *);
 """
@@ -183,6 +185,7 @@
 int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *, unsigned char **);
 BASIC_CONSTRAINTS *BASIC_CONSTRAINTS_new(void);
 void BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *);
+
 /* This is a macro defined by a call to DECLARE_ASN1_FUNCTIONS in the
    x509v3.h header. */
 void AUTHORITY_KEYID_free(AUTHORITY_KEYID *);
@@ -191,6 +194,9 @@
 void NAME_CONSTRAINTS_free(NAME_CONSTRAINTS *);
 
 void *X509V3_set_ctx_nodb(X509V3_CTX *);
+
+int i2d_GENERAL_NAMES(GENERAL_NAMES *, unsigned char **);
+
 int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *);
 int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *);
 GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int);
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 18faecb..c2a3dc2 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -146,6 +146,47 @@
     return extension
 
 
+def _encode_subject_alt_name(backend, san, critical):
+    obj = _txt2obj(backend, x509.OID_SUBJECT_ALTERNATIVE_NAME.dotted_string)
+    assert obj is not None
+
+    general_names = backend._lib.GENERAL_NAMES_new()
+    assert general_names != backend._ffi.NULL
+    # TODO: GC
+
+    for alt_name in san:
+        assert isinstance(alt_name, x509.DNSName)
+        gn = backend._lib.GENERAL_NAME_new()
+        assert gn != backend._ffi.NULL
+        gn.type = backend._lib.GEN_DNS
+        ia5 = backend._lib.ASN1_IA5STRING_new()
+        assert ia5 != backend._ffi.NULL
+        gn.d.dNSName = ia5
+        # TODO: idna
+        value = alt_name.value.encode("ascii")
+        res = backend._lib.ASN1_STRING_set(gn.d.dNSName, value, len(value))
+        assert res == 1
+
+        res = backend._lib.sk_GENERAL_NAME_push(general_names, gn)
+        assert res == 1
+
+    pp = backend._ffi.new("unsigned char **")
+    r = backend._lib.i2d_GENERAL_NAMES(general_names, pp)
+    assert r > 0
+    pp = backend._ffi.gc(
+        pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+    )
+
+    extension = backend._lib.X509_EXTENSION_create_by_OBJ(
+        backend._ffi.NULL,
+        obj,
+        1 if critical else 0,
+        _encode_asn1_str(backend, pp[0], r)
+    )
+    assert extension != backend._ffi.NULL
+    return extension
+
+
 @utils.register_interface(CipherBackend)
 @utils.register_interface(CMACBackend)
 @utils.register_interface(DERSerializationBackend)
@@ -857,6 +898,12 @@
                     extension.value,
                     extension.critical
                 )
+            elif isinstance(extension.value, x509.SubjectAlternativeName):
+                extension = _encode_subject_alt_name(
+                    self,
+                    extension.value,
+                    extension.critical,
+                )
             else:
                 raise NotImplementedError('Extension not yet supported.')
             res = self._lib.sk_X509_EXTENSION_push(extensions, extension)
diff --git a/tests/test_x509.py b/tests/test_x509.py
index df315cc..64a5923 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -884,6 +884,30 @@
                 ])
             )
 
+    def test_subject_alt_names(self, backend):
+        private_key = RSA_KEY_2048.private_key(backend)
+
+        csr = x509.CertificateSigningRequestBuilder().subject_name(
+            x509.Name([
+                x509.NameAttribute(x509.OID_COMMON_NAME, u"SAN"),
+            ])
+        ).add_extension(
+            x509.SubjectAlternativeName([
+                x509.DNSName(u"google.com"),
+            ]),
+            critical=False,
+        ).sign(private_key, hashes.SHA256(), backend)
+
+        assert len(csr.extensions) == 1
+        ext = csr.extensions.get_extension_for_oid(
+            x509.OID_SUBJECT_ALTERNATIVE_NAME
+        )
+        assert not ext.critical
+        assert ext.oid == x509.OID_SUBJECT_ALTERNATIVE_NAME
+        assert list(ext.value) == [
+            x509.DNSName(u"google.com"),
+        ]
+
 
 @pytest.mark.requires_backend_interface(interface=DSABackend)
 @pytest.mark.requires_backend_interface(interface=X509Backend)