When you create a SSL_CTX, using the function SSL_CTX_new, you need to pass as argument a method, as per the documentation:
https://www.openssl.org/docs/ssl/SSL_CTX_new.html
All methods have three variations: generic, client and server.
For example, you have TLSv1_method, TLSv1_server_method, TLSv1_client_method.
My questions are: when should I use the specific (client/server) methods? What are they good for? Can I always exchange then with the generic method?
when should I use the specific (client/server) methods? What are they good for?
I don't believe there is a significant difference when selecting a method
. You can use the generic method for a client and a server.
I believe the client are server methods provide a hint for use later in the library. From struct ssl_st
in ssl.h
:
/* Imagine that here's a boolean member "init" that is
* switched as soon as SSL_set_{accept/connect}_state
* is called for the first time, so that "state" and
* "handshake_func" are properly initialized. But as
* handshake_func is == 0 until then, we use this
* test instead of an "init" member.
*/
int server; /* are we the server side? - mostly used by SSL_clear*/
Interestingly, there's just one generic macro that handles them (generic, client, server). For example, the SSLv23 methods:
$ grep -R IMPLEMENT_ssl23_meth_func *
ssl/s23_clnt.c:IMPLEMENT_ssl23_meth_func(SSLv23_client_method,
ssl/s23_meth.c:IMPLEMENT_ssl23_meth_func(SSLv23_method,
ssl/s23_srvr.c:IMPLEMENT_ssl23_meth_func(SSLv23_server_method,
ssl/ssl_locl.h:#define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \
Then, in ssl/ssl_locl.h
:
#define IMPLEMENT_ssl23_meth_func(func_name, s_accept, s_connect, s_get_meth) \
const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
TLS1_2_VERSION, \
tls1_new, \
tls1_clear, \
tls1_free, \
s_accept, \
s_connect, \
ssl23_read, \
ssl23_peek, \
ssl23_write, \
ssl_undefined_function, \
ssl_undefined_function, \
ssl_ok, \
ssl3_get_message, \
ssl3_read_bytes, \
ssl3_write_bytes, \
ssl3_dispatch_alert, \
ssl3_ctrl, \
ssl3_ctx_ctrl, \
ssl23_get_cipher_by_char, \
ssl23_put_cipher_by_char, \
ssl_undefined_const_function, \
ssl23_num_ciphers, \
ssl23_get_cipher, \
s_get_meth, \
ssl23_default_timeout, \
&ssl3_undef_enc_method, \
ssl_undefined_void_function, \
ssl3_callback_ctrl, \
ssl3_ctx_callback_ctrl, \
}; \
return &func_name##_data; \
}
you have TLSv1_method, TLSv1_server_method, TLSv1_client_method.
Usually, you want something like the following to ensure "TLS 1.0 and above" rather than picking a specific method:
const SSL_METHOD* method = SSLv23_method();
SSL_CTX* ctx = SSL_CTX_new(method);
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
The library will do the right thing and pick the highest protocol (TLS 1.2, TLS 1.1, etc) and the strongest cipher (with some hand waiving).
The RFCs don't specify who "picks" the cipher, and OpenSSL leaves it to the client by default. If you are running the server, then you can use SSL_OP_CIPHER_SERVER_PREFERENCE
to ensure your server picks the cipher suite rather than taking the client's first choice. This is important because some clients are braindead and will select RSA key transport, RC4 and MD5 (and other weak/wounded/broken configurations).
If you use SSL_OP_CIPHER_SERVER_PREFERENCE
, then you need to make sure you have selected the appropriate cipher suites. I'd expect to see a cipher suite string with HIGH
, !ADH
, !RC4
, !MD5
, etc.