add custom extensions functions for openssl >=1.0.2 (#4202)

* add custom extensions functions for openssl >=1.0.2

* Fix style problems
diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py
index 2933114..4fdd6d6 100644
--- a/src/_cffi_src/openssl/ssl.py
+++ b/src/_cffi_src/openssl/ssl.py
@@ -48,6 +48,7 @@
 static const long Cryptography_HAS_ALPN;
 static const long Cryptography_HAS_NEXTPROTONEG;
 static const long Cryptography_HAS_SET_CERT_CB;
+static const long Cryptography_HAS_CUSTOM_EXT;
 
 static const long SSL_FILETYPE_PEM;
 static const long SSL_FILETYPE_ASN1;
@@ -488,6 +489,35 @@
 long DTLSv1_handle_timeout(SSL *);
 long DTLS_set_link_mtu(SSL *, long);
 long DTLS_get_link_min_mtu(SSL *);
+
+/* Custom extensions. */
+typedef int (*custom_ext_add_cb)(SSL *, unsigned int,
+                                 const unsigned char **,
+                                 size_t *, int *,
+                                 void *);
+
+typedef void (*custom_ext_free_cb)(SSL *, unsigned int,
+                                   const unsigned char *,
+                                   void *);
+
+typedef int (*custom_ext_parse_cb)(SSL *, unsigned int,
+                                   const unsigned char *,
+                                   size_t, int *,
+                                   void *);
+
+int SSL_CTX_add_client_custom_ext(SSL_CTX *, unsigned int,
+                                  custom_ext_add_cb,
+                                  custom_ext_free_cb, void *,
+                                  custom_ext_parse_cb,
+                                  void *);
+
+int SSL_CTX_add_server_custom_ext(SSL_CTX *, unsigned int,
+                                  custom_ext_add_cb,
+                                  custom_ext_free_cb, void *,
+                                  custom_ext_parse_cb,
+                                  void *);
+
+int SSL_extension_supported(unsigned int);
 """
 
 CUSTOMIZATIONS = """
@@ -708,4 +738,42 @@
 #else
 static const long Cryptography_HAS_PSK = 1;
 #endif
+
+/*
+ * Custom extensions were added in 1.0.2. 1.1.1 is adding a more general
+ * SSL_CTX_add_custom_ext function, but we're not binding that yet.
+ */
+#if CRYPTOGRAPHY_OPENSSL_102_OR_GREATER
+static const long Cryptography_HAS_CUSTOM_EXT = 1;
+#else
+static const long Cryptography_HAS_CUSTOM_EXT = 0;
+
+typedef int (*custom_ext_add_cb)(SSL *, unsigned int,
+                                 const unsigned char **,
+                                 size_t *, int *,
+                                 void *);
+
+typedef void (*custom_ext_free_cb)(SSL *, unsigned int,
+                                   const unsigned char *,
+                                   void *);
+
+typedef int (*custom_ext_parse_cb)(SSL *, unsigned int,
+                                   const unsigned char *,
+                                   size_t, int *,
+                                   void *);
+
+int (*SSL_CTX_add_client_custom_ext)(SSL_CTX *, unsigned int,
+                                     custom_ext_add_cb,
+                                     custom_ext_free_cb, void *,
+                                     custom_ext_parse_cb,
+                                     void *) = NULL;
+
+int (*SSL_CTX_add_server_custom_ext)(SSL_CTX *, unsigned int,
+                                     custom_ext_add_cb,
+                                     custom_ext_free_cb, void *,
+                                     custom_ext_parse_cb,
+                                     void *) = NULL;
+
+int (*SSL_extension_supported)(unsigned int) = NULL;
+#endif
 """
diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py
index 3cdafd6..971e540 100644
--- a/src/cryptography/hazmat/bindings/openssl/_conditional.py
+++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py
@@ -236,6 +236,14 @@
     ]
 
 
+def cryptography_has_custom_ext():
+    return [
+        "SSL_CTX_add_client_custom_ext",
+        "SSL_CTX_add_server_custom_ext",
+        "SSL_extension_supported",
+    ]
+
+
 # This is a mapping of
 # {condition: function-returning-names-dependent-on-that-condition} so we can
 # loop over them and delete unsupported names at runtime. It will be removed
@@ -287,4 +295,5 @@
     "Cryptography_HAS_FIPS": cryptography_has_fips,
     "Cryptography_HAS_SIGALGS": cryptography_has_ssl_sigalgs,
     "Cryptography_HAS_PSK": cryptography_has_psk,
+    "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext,
 }