5 // Created by Martin Baulig on 4/11/16.
6 // Copyright © 2016 Xamarin. All rights reserved.
9 #include <btls-ssl-ctx.h>
10 #include <btls-x509-verify-param.h>
12 struct MonoBtlsSslCtx {
13 CRYPTO_refcount_t references;
18 MonoBtlsVerifyFunc verify_func;
19 MonoBtlsSelectFunc select_func;
22 #define debug_print(ptr,message) \
23 do { if (mono_btls_ssl_ctx_is_debug_enabled(ptr)) \
24 mono_btls_ssl_ctx_debug_printf (ptr, "%s:%d:%s(): " message, __FILE__, __LINE__, \
25 __func__); } while (0)
27 #define debug_printf(ptr,fmt, ...) \
28 do { if (mono_btls_ssl_ctx_is_debug_enabled(ptr)) \
29 mono_btls_ssl_ctx_debug_printf (ptr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, \
30 __func__, __VA_ARGS__); } while (0)
32 void ssl_cipher_preference_list_free (struct ssl_cipher_preference_list_st *cipher_list);
35 mono_btls_ssl_ctx_is_debug_enabled (MonoBtlsSslCtx *ctx)
37 return ctx->debug_bio != NULL;
41 mono_btls_ssl_ctx_debug_printf (MonoBtlsSslCtx *ctx, const char *format, ...)
49 va_start (args, format);
50 ret = mono_btls_debug_printf (ctx->debug_bio, format, args);
55 MONO_API MonoBtlsSslCtx *
56 mono_btls_ssl_ctx_new (void)
60 ctx = OPENSSL_malloc (sizeof (MonoBtlsSslCtx));
64 memset (ctx, 0, sizeof (MonoBtlsSslCtx));
66 ctx->ctx = SSL_CTX_new (TLS_method ());
70 MONO_API MonoBtlsSslCtx *
71 mono_btls_ssl_ctx_up_ref (MonoBtlsSslCtx *ctx)
73 CRYPTO_refcount_inc (&ctx->references);
78 mono_btls_ssl_ctx_free (MonoBtlsSslCtx *ctx)
80 if (!CRYPTO_refcount_dec_and_test_zero (&ctx->references))
82 SSL_CTX_free (ctx->ctx);
89 mono_btls_ssl_ctx_get_ctx (MonoBtlsSslCtx *ctx)
95 mono_btls_ssl_ctx_set_debug_bio (MonoBtlsSslCtx *ctx, BIO *debug_bio)
98 ctx->debug_bio = BIO_up_ref(debug_bio);
100 ctx->debug_bio = NULL;
104 mono_btls_ssl_ctx_initialize (MonoBtlsSslCtx *ctx, void *instance)
106 ctx->instance = instance;
110 cert_verify_callback (X509_STORE_CTX *storeCtx, void *arg)
112 MonoBtlsSslCtx *ptr = (MonoBtlsSslCtx*)arg;
115 debug_printf (ptr, "cert_verify_callback(): %p\n", ptr->verify_func);
116 ret = X509_verify_cert (storeCtx);
117 debug_printf (ptr, "cert_verify_callback() #1: %d\n", ret);
119 if (ptr->verify_func)
120 ret = ptr->verify_func (ptr->instance, ret, storeCtx);
126 mono_btls_ssl_ctx_set_cert_verify_callback (MonoBtlsSslCtx *ptr, MonoBtlsVerifyFunc func, int cert_required)
130 ptr->verify_func = func;
131 SSL_CTX_set_cert_verify_callback (ptr->ctx, cert_verify_callback, ptr);
133 mode = SSL_VERIFY_PEER;
135 mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
137 SSL_CTX_set_verify (ptr->ctx, mode, NULL);
141 cert_select_callback (SSL *ssl, void *arg)
143 MonoBtlsSslCtx *ptr = (MonoBtlsSslCtx*)arg;
146 debug_printf (ptr, "cert_select_callback(): %p\n", ptr->select_func);
147 if (ptr->select_func)
148 ret = ptr->select_func (ptr->instance);
149 debug_printf (ptr, "cert_select_callback() #1: %d\n", ret);
155 mono_btls_ssl_ctx_set_cert_select_callback (MonoBtlsSslCtx *ptr, MonoBtlsSelectFunc func)
157 ptr->select_func = func;
158 SSL_CTX_set_cert_cb (ptr->ctx, cert_select_callback, ptr);
161 MONO_API X509_STORE *
162 mono_btls_ssl_ctx_peek_store (MonoBtlsSslCtx *ctx)
164 return SSL_CTX_get_cert_store (ctx->ctx);
168 mono_btls_ssl_ctx_set_min_version (MonoBtlsSslCtx *ctx, int version)
170 SSL_CTX_set_min_version (ctx->ctx, version);
174 mono_btls_ssl_ctx_set_max_version (MonoBtlsSslCtx *ctx, int version)
176 SSL_CTX_set_max_version (ctx->ctx, version);
180 mono_btls_ssl_ctx_is_cipher_supported (MonoBtlsSslCtx *ctx, uint16_t value)
182 const SSL_CIPHER *cipher;
184 cipher = SSL_get_cipher_by_value (value);
185 return cipher != NULL;
189 mono_btls_ssl_ctx_set_ciphers (MonoBtlsSslCtx *ctx, int count, const uint16_t *data,
190 int allow_unsupported)
192 STACK_OF(SSL_CIPHER) *ciphers = NULL;
193 struct ssl_cipher_preference_list_st *pref_list = NULL;
194 uint8_t *in_group_flags = NULL;
197 ciphers = sk_SSL_CIPHER_new_null ();
201 for (i = 0; i < count; i++) {
202 const SSL_CIPHER *cipher = SSL_get_cipher_by_value (data [i]);
204 debug_printf (ctx, "mono_btls_ssl_ctx_set_ciphers(): unknown cipher %02x", data [i]);
205 if (!allow_unsupported)
209 if (!sk_SSL_CIPHER_push (ciphers, cipher))
213 pref_list = OPENSSL_malloc (sizeof (struct ssl_cipher_preference_list_st));
217 memset (pref_list, 0, sizeof (struct ssl_cipher_preference_list_st));
218 pref_list->ciphers = sk_SSL_CIPHER_dup (ciphers);
219 if (!pref_list->ciphers)
221 pref_list->in_group_flags = OPENSSL_malloc (sk_SSL_CIPHER_num (ciphers));
222 if (!pref_list->in_group_flags)
225 if (ctx->ctx->cipher_list)
226 ssl_cipher_preference_list_free (ctx->ctx->cipher_list);
227 if (ctx->ctx->cipher_list_by_id)
228 sk_SSL_CIPHER_free (ctx->ctx->cipher_list_by_id);
229 if (ctx->ctx->cipher_list_tls10) {
230 ssl_cipher_preference_list_free (ctx->ctx->cipher_list_tls10);
231 ctx->ctx->cipher_list_tls10 = NULL;
233 if (ctx->ctx->cipher_list_tls11) {
234 ssl_cipher_preference_list_free (ctx->ctx->cipher_list_tls11);
235 ctx->ctx->cipher_list_tls11 = NULL;
238 ctx->ctx->cipher_list = pref_list;
239 ctx->ctx->cipher_list_by_id = ciphers;
241 return (int)sk_SSL_CIPHER_num (ciphers);
244 sk_SSL_CIPHER_free (ciphers);
245 OPENSSL_free (pref_list);
246 OPENSSL_free (in_group_flags);
251 mono_btls_ssl_ctx_set_verify_param (MonoBtlsSslCtx *ctx, const MonoBtlsX509VerifyParam *param)
253 return SSL_CTX_set1_param (ctx->ctx, mono_btls_x509_verify_param_peek_param (param));