TLS encryption used with websocket, websocket employed nopoll library.
cipher list: ECDHE_ECDSA_WITH_AES_128_CBC_SHA:ECDHE_ECDSA_WITH_AES_256_CBC_SHA:ECDHE_RSA_WITH_AES_128_CBC_SHA:ECDHE_RSA_WITH_AES_128_CBC_SHA
Different algorithms, different requirements for the certificate.
ECDHE_ECDSA: ECC certificate server used by the ECC certificate and signature verification;
ECDHE_RSA: ECC certificate used by the server, and there is RSA signature verification certificate;
ECC certificate generation process is as follows:
Generate a self-signed root certificate:
openssl ecparam -out EccCA.key -name secp521r1 -genkey openssl req -key EccCA.key -new -out EccCA.req -subj "/C=CN/ST=GuangZhou/L=GuangZhou/O=TEST/OU=TEST" openssl x509 -req -in EccCA.req -extensions v3_ca -signkey EccCA.key -out EccCA.pem
Client Certificate
openssl ecparam -out EccCA.key -name secp521r1 -genkey openssl req -key EccCA.key -new -out EccCA.req -subj "/C=CN/ST=GuangZhou/L=GuangZhou/O=TEST/OU=TEST" openssl x509 -req -in EccCA.req -extensions v3_ca -signkey EccCA.key -out EccCA.pem
nopoll code is implemented as follows:
Service-Terminal:
noPollPtr ssl_context_creator (noPollCtx * ctx, noPollConn * conn, noPollConnOpts * opts, nopoll_bool is_client, noPollPtr user_data)
{
SSL_CTX * ssl_ctx;
noPollConn * listener;
EC_KEY *ecdh = NULL;
/* very basic context creation using default settings provided
* by OpenSSL */
#if 0
if (is_client)
return SSL_CTX_new (TLSv1_client_method ());
#endif
/* get the ssl context */
ssl_ctx = SSL_CTX_new (TLSv1_2_server_method ());
/* get a reference to the listener */
listener = nopoll_conn_get_listener (conn);
if (nopoll_cmp ("1080", nopoll_conn_port (listener))) {
log_debug("ACCEPTED ssl connection on port: %s (for conn %p)\n", nopoll_conn_port (listener), conn);
if (!SSL_CTX_set_cipher_list(ssl_ctx, "ECDHE-ECDSA-AES256-SHA"))
// if (!SSL_CTX_set_cipher_list(ssl_ctx, "ECDH-RSA-AES256-SHA"))
{
log_error("Failed setting cipher list.");
}
ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
EC_KEY_free(ecdh);
} /* end if */
return ssl_ctx;
}
int main()
{ noPollConn *listener; noPollConnOpts * opts; if(0 == strcmp(auth, "Mutual")) { /* configure server certificates (server.pem) signed by the * provided ca (root.pem) also configured in the last * parameter */ if (! nopoll_conn_opts_set_ssl_certs (opts, MUTUAL_DTU_CERT, MUTUAL_DTU_KEY, NULL, MUTUAL_DTU_CERT)) { log_error("Unable to setup certificates...\n"); return ERROR; } /* configure peer verification */ nopoll_conn_opts_ssl_peer_verify( opts, nopoll_true ); nopoll_conn_opts_set_ssl_protocol( opts, NOPOLL_METHOD_SSLV23 ); listener = nopoll_listener_tls_new_opts( kea_ctx, opts, BIND_IP, LISTEN_PORT ); nopoll_ctx_set_ssl_context_creator (kea_ctx, ssl_context_creator, NULL); if (!nopoll_conn_is_ok(listener)) { log_error("can not bind to nopoll listener\n"); return ERROR; } } else { nopoll_conn_opts_set_ssl_protocol( opts, NOPOLL_METHOD_SSLV23 ); // nopoll_conn_opts_set_ssl_protocol( opts, NOPOLL_METHOD_SSLV3 ); listener = nopoll_listener_tls_new_opts( kea_ctx, opts, BIND_IP, LISTEN_PORT ); // listener = nopoll_listener_tls_new(kea_ctx, ANYESC_BIND_IP, ANYESC_LISTEN_PORT); nopoll_ctx_set_ssl_context_creator (kea_ctx, ssl_context_creator, NULL); if (!nopoll_conn_is_ok (listener)) { log_error("can not bind to nopoll listener\n"); return ERROR; } if (!nopoll_listener_set_certificate(listener, SINGE_CERT, SINGE_KEY, NULL)) { log_error("Unable to configure certificates for TLS websocket.."); return ERROR; } if (!nopoll_ctx_set_certificate(kea_ctx, NULL, ANYESC_SINGE_CERT, ANYESC_SINGE_KEY, NULL)) { log_error("Unable to setup certificates at context level.."); return ERROR; } } nopoll_ctx_set_on_msg(kea_ctx, kea_monitor_recv_msg, NULL); nopoll_ctx_set_on_open(kea_ctx, kea_on_connection_opened, NULL); while(1) { nopoll_loop_wait(kea_ctx, 0); } nopoll_conn_close(listener); nopoll_ctx_unref(kea_ctx); nopoll_cleanup_library();
return 0; }
Client code to achieve the following:
int nopoll_test_main (int argc, char **argv) { noPollCtx * ctx; noPollConn * conn; noPollConnOpts * opts; ctx = create_ctx (); if(0 == strcmp("single", argv[1])) { opts = nopoll_conn_opts_new (); nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_SSLV23); nopoll_conn_opts_ssl_peer_verify (opts, nopoll_true); nopoll_conn_opts_set_ssl_certs (opts, /* certificate */ NULL, /* private key */ NULL, NULL, /* ca certificate */ ANYESC_SINGE_CA_CERT); conn = nopoll_conn_tls_new (ctx, opts, ANYESC_BIND_IP, ANYESC_LISTEN_PORT, NULL, NULL, NULL, NULL); if (! nopoll_conn_wait_until_connection_ready (conn, 5)) { log_notice("Expected a FAILING connection status due to origing denied"); return; } nopoll_conn_send_text(conn, "test nopoll", 11); nopoll_conn_close (conn); } else { opts = nopoll_conn_opts_new (); nopoll_conn_opts_set_ssl_certs (opts, /* certificate */ ANYESC_MUTUAL_AE_CERT, /* private key */ ANYESC_MUTUAL_AE_KEY, NULL, /* ca certificate */ ANYESC_MUTUAL_DTU_CERT); nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_SSLV23); conn = nopoll_conn_tls_new (ctx, opts, "192.168.1.1", "1080", NULL, NULL, NULL, NULL); if (! nopoll_conn_wait_until_connection_ready (conn, 5)) { log_notice("Expected a FAILING connection status due to origing denied"); return; } nopoll_conn_send_text(conn, "test nopoll", 11); nopoll_conn_close (conn); } nopoll_ctx_unref (ctx); return 0; }