summaryrefslogtreecommitdiffstats
path: root/tinyNET/src/tls/tnet_dtls.c
diff options
context:
space:
mode:
Diffstat (limited to 'tinyNET/src/tls/tnet_dtls.c')
-rwxr-xr-xtinyNET/src/tls/tnet_dtls.c1166
1 files changed, 585 insertions, 581 deletions
diff --git a/tinyNET/src/tls/tnet_dtls.c b/tinyNET/src/tls/tnet_dtls.c
index 6420c9e..b49bd46 100755
--- a/tinyNET/src/tls/tnet_dtls.c
+++ b/tinyNET/src/tls/tnet_dtls.c
@@ -33,46 +33,45 @@
#include "tsk_safeobj.h"
#include "tsk_debug.h"
-typedef struct tnet_dtls_socket_s
-{
- TSK_DECLARE_OBJECT;
-
- struct tnet_socket_s* wrapped_sock; /* not owner: do not try to close */
- tsk_bool_t verify_peer;
- tsk_bool_t use_srtp;
- tsk_bool_t handshake_completed;
- tsk_bool_t handshake_started;
- tsk_bool_t handshake_storedata; // whether to store handshaking data or to send it to the remote party
- tnet_dtls_setup_t setup;
-
- struct {
- void* ptr;
- tsk_size_t size;
- tsk_size_t count;
- } handshake_data;
-
- struct{
- const void* usrdata;
- tnet_dtls_socket_cb_f func;
- } cb;
-
- struct{
- tnet_fingerprint_t fp;
- tnet_dtls_hash_type_t hash;
- struct sockaddr_storage addr;
- } remote;
- struct{
- tnet_fingerprint_t fp;
- tnet_dtls_hash_type_t hash;
- } local;
+typedef struct tnet_dtls_socket_s {
+ TSK_DECLARE_OBJECT;
+
+ struct tnet_socket_s* wrapped_sock; /* not owner: do not try to close */
+ tsk_bool_t verify_peer;
+ tsk_bool_t use_srtp;
+ tsk_bool_t handshake_completed;
+ tsk_bool_t handshake_started;
+ tsk_bool_t handshake_storedata; // whether to store handshaking data or to send it to the remote party
+ tnet_dtls_setup_t setup;
+
+ struct {
+ void* ptr;
+ tsk_size_t size;
+ tsk_size_t count;
+ } handshake_data;
+
+ struct {
+ const void* usrdata;
+ tnet_dtls_socket_cb_f func;
+ } cb;
+
+ struct {
+ tnet_fingerprint_t fp;
+ tnet_dtls_hash_type_t hash;
+ struct sockaddr_storage addr;
+ } remote;
+ struct {
+ tnet_fingerprint_t fp;
+ tnet_dtls_hash_type_t hash;
+ } local;
#if HAVE_OPENSSL
- SSL *ssl;
- BIO* rbio;
- BIO* wbio;
+ SSL *ssl;
+ BIO* rbio;
+ BIO* wbio;
#endif
- TSK_DECLARE_SAFEOBJ;
+ TSK_DECLARE_SAFEOBJ;
}
tnet_dtls_socket_t;
@@ -83,18 +82,18 @@ tnet_dtls_socket_t;
tsk_bool_t tnet_dtls_is_srtp_supported()
{
#if HAVE_OPENSSL_DTLS_SRTP
- return tsk_true;
+ return tsk_true;
#else
- return tsk_false;
+ return tsk_false;
#endif
}
tsk_bool_t tnet_dtls_is_supported()
{
#if HAVE_OPENSSL_DTLS
- return tsk_true;
+ return tsk_true;
#else
- return tsk_false;
+ return tsk_false;
#endif
}
@@ -105,298 +104,304 @@ static tsk_bool_t _tnet_dtls_is_fingerprint_matching(X509* cert, tnet_fingerprin
static int _tnet_dtls_verify_cert(int preverify_ok, X509_STORE_CTX *ctx)
{
- SSL *ssl;
- tnet_dtls_socket_t* socket;
-
- TSK_DEBUG_INFO("_tnet_dtls_verify_cert");
-
- ssl = X509_STORE_CTX_get_app_data(ctx);
- socket = (tnet_dtls_socket_t*)SSL_get_app_data(ssl);
- if (!ssl || !socket){
- TSK_DEBUG_ERROR("Not expected");
- return 0;
- }
- tsk_safeobj_lock(socket);
- if (_tnet_dtls_is_fingerprint_matching(ctx->cert, &socket->remote.fp, socket->remote.hash) == tsk_false) {
- TSK_DEBUG_ERROR("Failed to match fingerprint");
- tsk_safeobj_unlock(socket);
- return 0;
- }
- tsk_safeobj_unlock(socket);
- return 1;
+ SSL *ssl;
+ tnet_dtls_socket_t* socket;
+
+ TSK_DEBUG_INFO("_tnet_dtls_verify_cert");
+
+ ssl = X509_STORE_CTX_get_app_data(ctx);
+ socket = (tnet_dtls_socket_t*)SSL_get_app_data(ssl);
+ if (!ssl || !socket) {
+ TSK_DEBUG_ERROR("Not expected");
+ return 0;
+ }
+ tsk_safeobj_lock(socket);
+ if (_tnet_dtls_is_fingerprint_matching(ctx->cert, &socket->remote.fp, socket->remote.hash) == tsk_false) {
+ TSK_DEBUG_ERROR("Failed to match fingerprint");
+ tsk_safeobj_unlock(socket);
+ return 0;
+ }
+ tsk_safeobj_unlock(socket);
+ return 1;
}
static const EVP_MD *_tnet_dtls_get_hash_evp(tnet_dtls_hash_type_t hash)
{
- switch (hash){
- case tnet_dtls_hash_type_md5: return EVP_md5();
- case tnet_dtls_hash_type_sha1: return EVP_sha1();
- case tnet_dtls_hash_type_sha256: return EVP_sha256();
- case tnet_dtls_hash_type_sha512: return EVP_sha512();
- default: TSK_DEBUG_ERROR("Invalid parameter: %d not valid as hash type", hash); return tsk_null;
- }
+ switch (hash) {
+ case tnet_dtls_hash_type_md5:
+ return EVP_md5();
+ case tnet_dtls_hash_type_sha1:
+ return EVP_sha1();
+ case tnet_dtls_hash_type_sha256:
+ return EVP_sha256();
+ case tnet_dtls_hash_type_sha512:
+ return EVP_sha512();
+ default:
+ TSK_DEBUG_ERROR("Invalid parameter: %d not valid as hash type", hash);
+ return tsk_null;
+ }
}
static int _tnet_dtls_get_fingerprint(X509* cert, const EVP_MD *evp, tnet_fingerprint_t* fingerprint)
{
- if (!cert || !evp || !fingerprint){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- else{
- unsigned len = 0, i, j;
- tnet_fingerprint_t fp;
-
- if (X509_digest(cert, evp, fp, &len) != 1 || len <= 0){
- TSK_DEBUG_ERROR("X509_digest() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- return -2;
- }
- for (i = 0, j = 0; i < len; ++i, j += 3){
- sprintf((char*)&(*fingerprint)[j], (i == (len - 1)) ? "%.2X" : "%.2X:", fp[i]);
- }
- (*fingerprint)[len * 3] = '\0';
- return 0;
- }
+ if (!cert || !evp || !fingerprint) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ else {
+ unsigned len = 0, i, j;
+ tnet_fingerprint_t fp;
+
+ if (X509_digest(cert, evp, fp, &len) != 1 || len <= 0) {
+ TSK_DEBUG_ERROR("X509_digest() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ return -2;
+ }
+ for (i = 0, j = 0; i < len; ++i, j += 3) {
+ sprintf((char*)&(*fingerprint)[j], (i == (len - 1)) ? "%.2X" : "%.2X:", fp[i]);
+ }
+ (*fingerprint)[len * 3] = '\0';
+ return 0;
+ }
}
static tsk_bool_t _tnet_dtls_is_fingerprint_matching(X509* cert, tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash)
{
- const EVP_MD* evp;
- tnet_fingerprint_t fp;
- int ret;
-
- if (!cert || !fingerprint){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
-
- if (!(evp = _tnet_dtls_get_hash_evp(hash))){
- return tsk_false;
- }
- if ((ret = _tnet_dtls_get_fingerprint(cert, evp, &fp))){
- return tsk_false;
- }
- if (!tsk_striequals(fp, fingerprint)){
- TSK_DEBUG_ERROR("DTLS certificate fingerprints mismatch: [%s]#[%s]", fp, *fingerprint);
- return tsk_false;
- }
- return tsk_true;
+ const EVP_MD* evp;
+ tnet_fingerprint_t fp;
+ int ret;
+
+ if (!cert || !fingerprint) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+
+ if (!(evp = _tnet_dtls_get_hash_evp(hash))) {
+ return tsk_false;
+ }
+ if ((ret = _tnet_dtls_get_fingerprint(cert, evp, &fp))) {
+ return tsk_false;
+ }
+ if (!tsk_striequals(fp, fingerprint)) {
+ TSK_DEBUG_ERROR("DTLS certificate fingerprints mismatch: [%s]#[%s]", fp, *fingerprint);
+ return tsk_false;
+ }
+ return tsk_true;
}
static tsk_bool_t _tnet_dtls_socket_is_remote_cert_fp_match(tnet_dtls_socket_t* socket)
{
- if (!socket){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_false;
- }
- else if (socket->verify_peer){
- X509* cert;
-
- if (!(cert = SSL_get_peer_certificate(socket->ssl))){
- if (socket->verify_peer){ // print error only if verify certs is enabled
- TSK_DEBUG_ERROR("Failed to get peer certificate [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- }
- return tsk_false;
- }
- if (!_tnet_dtls_is_fingerprint_matching(cert, &socket->remote.fp, socket->remote.hash)){
- X509_free(cert);
- return tsk_false;
- }
- X509_free(cert);
-
- if (SSL_get_verify_result(socket->ssl) != X509_V_OK){
- TSK_DEBUG_ERROR("SSL_get_verify_result()#X509_V_OK [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- return tsk_false;
- }
- }
-
- return tsk_true;
+ if (!socket) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_false;
+ }
+ else if (socket->verify_peer) {
+ X509* cert;
+
+ if (!(cert = SSL_get_peer_certificate(socket->ssl))) {
+ if (socket->verify_peer) { // print error only if verify certs is enabled
+ TSK_DEBUG_ERROR("Failed to get peer certificate [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ }
+ return tsk_false;
+ }
+ if (!_tnet_dtls_is_fingerprint_matching(cert, &socket->remote.fp, socket->remote.hash)) {
+ X509_free(cert);
+ return tsk_false;
+ }
+ X509_free(cert);
+
+ if (SSL_get_verify_result(socket->ssl) != X509_V_OK) {
+ TSK_DEBUG_ERROR("SSL_get_verify_result()#X509_V_OK [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ return tsk_false;
+ }
+ }
+
+ return tsk_true;
}
#endif /* HAVE_OPENSSL */
tnet_dtls_hash_type_t tnet_dtls_get_hash_from_string(const char* hash)
{
- if (hash){
- int32_t i;
- for (i = 0; i < TNET_DTLS_HASH_TYPE_MAX; ++i){
- if (tsk_striequals(TNET_DTLS_HASH_NAMES[i], hash)){
- return (tnet_dtls_hash_type_t)i;
- }
- }
- }
- return tnet_dtls_hash_type_none;
+ if (hash) {
+ int32_t i;
+ for (i = 0; i < TNET_DTLS_HASH_TYPE_MAX; ++i) {
+ if (tsk_striequals(TNET_DTLS_HASH_NAMES[i], hash)) {
+ return (tnet_dtls_hash_type_t)i;
+ }
+ }
+ }
+ return tnet_dtls_hash_type_none;
}
tnet_dtls_setup_t tnet_dtls_get_setup_from_string(const char* setup)
{
- if (setup){
- int32_t i;
- for (i = 0; i < TNET_DTLS_SETUP_MAX; ++i){
- if (tsk_striequals(TNET_DTLS_SETUP_NAMES[i], setup)){
- return (tnet_dtls_setup_t)i;
- }
- }
- }
- return tnet_dtls_setup_none;
+ if (setup) {
+ int32_t i;
+ for (i = 0; i < TNET_DTLS_SETUP_MAX; ++i) {
+ if (tsk_striequals(TNET_DTLS_SETUP_NAMES[i], setup)) {
+ return (tnet_dtls_setup_t)i;
+ }
+ }
+ }
+ return tnet_dtls_setup_none;
}
int tnet_dtls_get_fingerprint(const char* certfile, tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return -200;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return -200;
#else
- {
- X509* x509;
- BIO* bio;
- int ret = 0;
- const EVP_MD *evp;
-
- if (tsk_strnullORempty(certfile) || !fingerprint){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if (!(evp = _tnet_dtls_get_hash_evp(hash))){
- return -1;
- }
-
- x509 = tsk_null;
- bio = tsk_null;
-
- if (!(bio = BIO_new(BIO_s_file()))){
- TSK_DEBUG_ERROR("BIO_new(BIO_s_file()) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- ret = -3;
- goto bail;
- }
- if (BIO_read_filename(bio, certfile) != 1){
- TSK_DEBUG_ERROR("BIO_read_filename(%s) failed [%s]", certfile, ERR_error_string(ERR_get_error(), tsk_null));
- ret = -4;
- goto bail;
- }
- if (!(x509 = PEM_read_bio_X509(bio, tsk_null, 0, tsk_null))){
- TSK_DEBUG_ERROR("PEM_read_bio() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- ret = -5;
- goto bail;
- }
- if ((ret = _tnet_dtls_get_fingerprint(x509, evp, fingerprint))){
- goto bail;
- }
-
- bail:
- if (bio){
- BIO_free_all(bio);
- }
- return ret;
- }
+ {
+ X509* x509;
+ BIO* bio;
+ int ret = 0;
+ const EVP_MD *evp;
+
+ if (tsk_strnullORempty(certfile) || !fingerprint) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if (!(evp = _tnet_dtls_get_hash_evp(hash))) {
+ return -1;
+ }
+
+ x509 = tsk_null;
+ bio = tsk_null;
+
+ if (!(bio = BIO_new(BIO_s_file()))) {
+ TSK_DEBUG_ERROR("BIO_new(BIO_s_file()) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ ret = -3;
+ goto bail;
+ }
+ if (BIO_read_filename(bio, certfile) != 1) {
+ TSK_DEBUG_ERROR("BIO_read_filename(%s) failed [%s]", certfile, ERR_error_string(ERR_get_error(), tsk_null));
+ ret = -4;
+ goto bail;
+ }
+ if (!(x509 = PEM_read_bio_X509(bio, tsk_null, 0, tsk_null))) {
+ TSK_DEBUG_ERROR("PEM_read_bio() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ ret = -5;
+ goto bail;
+ }
+ if ((ret = _tnet_dtls_get_fingerprint(x509, evp, fingerprint))) {
+ goto bail;
+ }
+
+bail:
+ if (bio) {
+ BIO_free_all(bio);
+ }
+ return ret;
+ }
#endif
}
tnet_dtls_socket_handle_t* tnet_dtls_socket_create(struct tnet_socket_s* wrapped_sock, struct ssl_ctx_st* ssl_ctx)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return tsk_null;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return tsk_null;
#else
- tnet_dtls_socket_t* socket;
-
- if (!wrapped_sock || !ssl_ctx){
- TSK_DEBUG_ERROR("Invalid parameter");
- return tsk_null;
- }
- if ((socket = tsk_object_new(tnet_dtls_socket_def_t))) {
- EC_KEY* ecdh;
- const tsk_bool_t set_mtu = TNET_SOCKET_TYPE_IS_DGRAM(wrapped_sock->type) || 1; //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
- socket->wrapped_sock = tsk_object_ref(wrapped_sock);
- if (!(socket->ssl = SSL_new(ssl_ctx))) {
- TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- TSK_OBJECT_SAFE_FREE(socket);
- return tsk_null;
- }
- if (set_mtu) {
- SSL_set_options(socket->ssl, SSL_OP_NO_QUERY_MTU);
- SSL_set_mtu(socket->ssl, TNET_DTLS_MTU - 28);
- socket->ssl->d1->mtu = TNET_DTLS_MTU - 28;
- }
- if (!(socket->rbio = BIO_new(BIO_s_mem())) || !(socket->wbio = BIO_new(BIO_s_mem()))){
- TSK_DEBUG_ERROR("BIO_new_socket(%d) failed [%s]", socket->wrapped_sock->fd, ERR_error_string(ERR_get_error(), tsk_null));
- if (socket->rbio){
- BIO_free(socket->rbio);
- }
- if (socket->wbio){
- BIO_free(socket->wbio);
- }
- TSK_OBJECT_SAFE_FREE(socket);
- return tsk_null;
- }
- BIO_set_mem_eof_return(socket->rbio, -1);
- BIO_set_mem_eof_return(socket->wbio, -1);
- SSL_set_bio(socket->ssl, socket->rbio, socket->wbio);
- SSL_set_mode(socket->ssl, SSL_MODE_AUTO_RETRY);
- SSL_set_read_ahead(socket->ssl, 1);
- // https://groups.google.com/forum/#!topic/doubango/Oo0t1e3tlL8
- if ((ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1))) {
- SSL_set_options(socket->ssl, SSL_OP_SINGLE_ECDH_USE);
- SSL_set_tmp_ecdh(socket->ssl, ecdh);
- EC_KEY_free(ecdh);
- }
-
- if (set_mtu) {
- BIO_ctrl(SSL_get_wbio(socket->ssl), BIO_CTRL_DGRAM_SET_MTU, TNET_DTLS_MTU - 28, NULL);
- }
-
- if ((socket->verify_peer = (SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE))){
- TSK_DEBUG_INFO("SSL cert verify: ON");
- socket->verify_peer = tsk_true;
- SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert);
- }
- else {
- TSK_DEBUG_ERROR("Verity not enabled");
- }
-
- SSL_set_app_data(socket->ssl, socket);
- }
- return socket;
+ tnet_dtls_socket_t* socket;
+
+ if (!wrapped_sock || !ssl_ctx) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_null;
+ }
+ if ((socket = tsk_object_new(tnet_dtls_socket_def_t))) {
+ EC_KEY* ecdh;
+ const tsk_bool_t set_mtu = TNET_SOCKET_TYPE_IS_DGRAM(wrapped_sock->type) || 1; //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
+ socket->wrapped_sock = tsk_object_ref(wrapped_sock);
+ if (!(socket->ssl = SSL_new(ssl_ctx))) {
+ TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ TSK_OBJECT_SAFE_FREE(socket);
+ return tsk_null;
+ }
+ if (set_mtu) {
+ SSL_set_options(socket->ssl, SSL_OP_NO_QUERY_MTU);
+ SSL_set_mtu(socket->ssl, TNET_DTLS_MTU - 28);
+ socket->ssl->d1->mtu = TNET_DTLS_MTU - 28;
+ }
+ if (!(socket->rbio = BIO_new(BIO_s_mem())) || !(socket->wbio = BIO_new(BIO_s_mem()))) {
+ TSK_DEBUG_ERROR("BIO_new_socket(%d) failed [%s]", socket->wrapped_sock->fd, ERR_error_string(ERR_get_error(), tsk_null));
+ if (socket->rbio) {
+ BIO_free(socket->rbio);
+ }
+ if (socket->wbio) {
+ BIO_free(socket->wbio);
+ }
+ TSK_OBJECT_SAFE_FREE(socket);
+ return tsk_null;
+ }
+ BIO_set_mem_eof_return(socket->rbio, -1);
+ BIO_set_mem_eof_return(socket->wbio, -1);
+ SSL_set_bio(socket->ssl, socket->rbio, socket->wbio);
+ SSL_set_mode(socket->ssl, SSL_MODE_AUTO_RETRY);
+ SSL_set_read_ahead(socket->ssl, 1);
+ // https://groups.google.com/forum/#!topic/doubango/Oo0t1e3tlL8
+ if ((ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1))) {
+ SSL_set_options(socket->ssl, SSL_OP_SINGLE_ECDH_USE);
+ SSL_set_tmp_ecdh(socket->ssl, ecdh);
+ EC_KEY_free(ecdh);
+ }
+
+ if (set_mtu) {
+ BIO_ctrl(SSL_get_wbio(socket->ssl), BIO_CTRL_DGRAM_SET_MTU, TNET_DTLS_MTU - 28, NULL);
+ }
+
+ if ((socket->verify_peer = (SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE))) {
+ TSK_DEBUG_INFO("SSL cert verify: ON");
+ socket->verify_peer = tsk_true;
+ SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert);
+ }
+ else {
+ TSK_DEBUG_ERROR("Verity not enabled");
+ }
+
+ SSL_set_app_data(socket->ssl, socket);
+ }
+ return socket;
#endif
}
tnet_fd_t tnet_dtls_socket_get_fd(const tnet_dtls_socket_handle_t* handle)
{
- return handle ? ((const tnet_dtls_socket_t*)handle)->wrapped_sock->fd : TNET_INVALID_FD;
+ return handle ? ((const tnet_dtls_socket_t*)handle)->wrapped_sock->fd : TNET_INVALID_FD;
}
const struct sockaddr_storage* tnet_dtls_socket_get_remote_addr(const tnet_dtls_socket_handle_t* handle)
{
- return handle ? &((const tnet_dtls_socket_t*)handle)->remote.addr : tsk_null;
+ return handle ? &((const tnet_dtls_socket_t*)handle)->remote.addr : tsk_null;
}
int tnet_dtls_socket_set_callback(tnet_dtls_socket_handle_t* handle, const void* usrdata, tnet_dtls_socket_cb_f func)
{
- tnet_dtls_socket_t* socket = handle;
+ tnet_dtls_socket_t* socket = handle;
- if (!socket){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!socket) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- socket->cb.usrdata = usrdata;
- socket->cb.func = func;
- return 0;
+ socket->cb.usrdata = usrdata;
+ socket->cb.func = func;
+ return 0;
}
int tnet_dtls_socket_set_remote_fingerprint(tnet_dtls_socket_handle_t* handle, const tnet_fingerprint_t* fingerprint, tnet_dtls_hash_type_t hash)
{
- tnet_dtls_socket_t* socket = handle;
+ tnet_dtls_socket_t* socket = handle;
- if (!socket || !fingerprint){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
+ if (!socket || !fingerprint) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
- memcpy(socket->remote.fp, &(*fingerprint)[0], sizeof(tnet_fingerprint_t));
- socket->remote.hash = hash;
- return 0;
+ memcpy(socket->remote.fp, &(*fingerprint)[0], sizeof(tnet_fingerprint_t));
+ socket->remote.hash = hash;
+ return 0;
}
/*
@@ -405,267 +410,267 @@ rfc5764: 4.1. The use_srtp Extension
int tnet_dtls_socket_use_srtp(tnet_dtls_socket_handle_t*handle)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS || !HAVE_OPENSSL_DTLS_SRTP
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return -200;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return -200;
#else
- tnet_dtls_socket_t* socket = handle;
- if (!socket){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- if ((socket->use_srtp = tsk_true)){
- if (!socket->verify_peer){
- socket->verify_peer = tsk_true; // DTLS-SRTP requires certtificates
- SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert);
- }
- }
- return 0;
+ tnet_dtls_socket_t* socket = handle;
+ if (!socket) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if ((socket->use_srtp = tsk_true)) {
+ if (!socket->verify_peer) {
+ socket->verify_peer = tsk_true; // DTLS-SRTP requires certtificates
+ SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert);
+ }
+ }
+ return 0;
#endif
}
int tnet_dtls_socket_set_setup(tnet_dtls_socket_handle_t* handle, tnet_dtls_setup_t setup)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return -200;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return -200;
#else
- tnet_dtls_socket_t* socket = handle;
- if (!socket){
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- switch ((socket->setup = setup)){
- case tnet_dtls_setup_passive:
- SSL_set_accept_state(socket->ssl);
- break;
- case tnet_dtls_setup_active:
- case tnet_dtls_setup_actpass:
- case tnet_dtls_setup_none:
- if (setup != tnet_dtls_setup_active){
- TSK_DEBUG_WARN("using setup=%s is not a good idea", TNET_DTLS_SETUP_NAMES[setup]);
- }
- SSL_set_connect_state(socket->ssl);
- break;
- default:
- TSK_DEBUG_ERROR("%d not valid value for DTLS setup", (int32_t)setup);
- break;
- }
- return 0;
+ tnet_dtls_socket_t* socket = handle;
+ if (!socket) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ switch ((socket->setup = setup)) {
+ case tnet_dtls_setup_passive:
+ SSL_set_accept_state(socket->ssl);
+ break;
+ case tnet_dtls_setup_active:
+ case tnet_dtls_setup_actpass:
+ case tnet_dtls_setup_none:
+ if (setup != tnet_dtls_setup_active) {
+ TSK_DEBUG_WARN("using setup=%s is not a good idea", TNET_DTLS_SETUP_NAMES[setup]);
+ }
+ SSL_set_connect_state(socket->ssl);
+ break;
+ default:
+ TSK_DEBUG_ERROR("%d not valid value for DTLS setup", (int32_t)setup);
+ break;
+ }
+ return 0;
#endif
}
int tnet_dtls_socket_set_store_handshakingdata(tnet_dtls_socket_handle_t* handle, tsk_bool_t handshake_storedata)
{
- if (!handle) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- ((tnet_dtls_socket_t*)handle)->handshake_storedata = handshake_storedata;
- return 0;
+ if (!handle) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ ((tnet_dtls_socket_t*)handle)->handshake_storedata = handshake_storedata;
+ return 0;
}
int tnet_dtls_socket_get_handshakingdata(tnet_dtls_socket_handle_t* handle, const void** data, tsk_size_t *size)
{
- if (!handle || !data || !size) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- *data = ((tnet_dtls_socket_t*)handle)->handshake_data.ptr;
- *size = ((tnet_dtls_socket_t*)handle)->handshake_data.count;
- return 0;
+ if (!handle || !data || !size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ *data = ((tnet_dtls_socket_t*)handle)->handshake_data.ptr;
+ *size = ((tnet_dtls_socket_t*)handle)->handshake_data.count;
+ return 0;
}
// This function returns first DTLS record. It's useful to send handshaking data by records to avoid IP fragmentation
int tnet_dtls_socket_get_record_first(const void* records, tsk_size_t records_size, const void** record, tsk_size_t* size)
{
- /* https://tools.ietf.org/html/rfc6347#section-3.2.3
- TLS and DTLS handshake messages can be quite large(in theory up to
- 2 ^ 24 - 1 bytes, in practice many kilobytes).By contrast, UDP
- datagrams are often limited to <1500 bytes if IP fragmentation is not
- desired.In order to compensate for this limitation, each DTLS
- handshake message may be fragmented over several DTLS records, each
- of which is intended to fit in a single IP datagram.Each DTLS
- handshake message contains both a fragment offset and a fragment
- length.Thus, a recipient in possession of all bytes of a handshake
- message can reassemble the original unfragmented message. */
- // 4.1. Record Layer - https://tools.ietf.org/html/rfc6347#section-4.1
+ /* https://tools.ietf.org/html/rfc6347#section-3.2.3
+ TLS and DTLS handshake messages can be quite large(in theory up to
+ 2 ^ 24 - 1 bytes, in practice many kilobytes).By contrast, UDP
+ datagrams are often limited to <1500 bytes if IP fragmentation is not
+ desired.In order to compensate for this limitation, each DTLS
+ handshake message may be fragmented over several DTLS records, each
+ of which is intended to fit in a single IP datagram.Each DTLS
+ handshake message contains both a fragment offset and a fragment
+ length.Thus, a recipient in possession of all bytes of a handshake
+ message can reassemble the original unfragmented message. */
+ // 4.1. Record Layer - https://tools.ietf.org/html/rfc6347#section-4.1
#define kDTLSv1RecordHdrStartIndex 11
#define kDTLSv1RecordHdrLengthFieldLen 2 // uint16
#define kDTLSv1RecordHdrLen (kDTLSv1RecordHdrStartIndex + kDTLSv1RecordHdrLengthFieldLen)
-
- const uint8_t* pc_records;
- tsk_size_t record_length;
- if (!records || records_size < kDTLSv1RecordHdrLen || !record || !size) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
- pc_records = (const uint8_t*)records;
- record_length = ((pc_records[kDTLSv1RecordHdrStartIndex] << 8) & 0xFF00) | (pc_records[kDTLSv1RecordHdrStartIndex + 1] & 0xFF);
- *record = records;
- *size = kDTLSv1RecordHdrLen + record_length;
- if ((*size) > TNET_DTLS_MTU) {
- TSK_DEBUG_WARN("DTLS record length(%u) > MTU(%u)", (unsigned)(*size), TNET_DTLS_MTU);
- }
-
- return 0;
+
+ const uint8_t* pc_records;
+ tsk_size_t record_length;
+ if (!records || records_size < kDTLSv1RecordHdrLen || !record || !size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ pc_records = (const uint8_t*)records;
+ record_length = ((pc_records[kDTLSv1RecordHdrStartIndex] << 8) & 0xFF00) | (pc_records[kDTLSv1RecordHdrStartIndex + 1] & 0xFF);
+ *record = records;
+ *size = kDTLSv1RecordHdrLen + record_length;
+ if ((*size) > TNET_DTLS_MTU) {
+ TSK_DEBUG_WARN("DTLS record length(%u) > MTU(%u)", (unsigned)(*size), TNET_DTLS_MTU);
+ }
+
+ return 0;
}
tsk_bool_t tnet_dtls_socket_is_remote_cert_fp_match(tnet_dtls_socket_handle_t* handle)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return -1;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return -1;
#else
- return _tnet_dtls_socket_is_remote_cert_fp_match((tnet_dtls_socket_t*)handle);
+ return _tnet_dtls_socket_is_remote_cert_fp_match((tnet_dtls_socket_t*)handle);
#endif
}
int tnet_dtls_socket_do_handshake(tnet_dtls_socket_handle_t* handle, const struct sockaddr_storage* remote_addr)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return -1;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return -1;
#else
- tnet_dtls_socket_t *socket = handle;
- int ret = 0, len;
- void* out_data;
-
- if (!socket) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- tsk_safeobj_lock(socket);
-
- // update remote address even if handshaking is completed
- if (remote_addr) {
- socket->remote.addr = *remote_addr;
- }
-
- if (socket->handshake_completed) {
- TSK_DEBUG_INFO("Handshake completed");
- ret = 0;
- goto bail;
- }
-
- if (!socket->handshake_started) {
- if ((ret = SSL_do_handshake(socket->ssl)) != 1) {
- switch ((ret = SSL_get_error(socket->ssl, ret))) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_NONE:
- break;
- default:
- TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed);
- ret = -2;
- goto bail;
- }
- }
- socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation
- }
-
- if ((len = (int)BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) {
- if (socket->handshake_storedata) { // e.g. when TURN is enabled we have to query handshaking data and sent it via the negotiated channel
- if ((int)socket->handshake_data.size < len) {
- if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) {
- socket->handshake_data.size = 0;
- socket->handshake_data.count = 0;
- ret = -5;
- goto bail;
- }
- socket->handshake_data.size = len;
- }
- socket->handshake_data.count = len;
- memcpy(socket->handshake_data.ptr, out_data, len);
- }
- else {
- int sentlen = 0;
- tnet_port_t port;
- tnet_ip_t ip;
- tsk_bool_t is_dgram = TNET_SOCKET_TYPE_IS_DGRAM(socket->wrapped_sock->type);
- const uint8_t *record_ptr, *records_ptr = out_data;
- tsk_size_t record_size;
- int records_len = len;
-
- tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port);
- TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, from(%.*s/%d) to(%.*s/%d)", len, (int)sizeof(socket->wrapped_sock->ip), socket->wrapped_sock->ip, socket->wrapped_sock->port, (int)sizeof(ip), ip, port);
-
- //!\ IP fragmentation issues must be avoided even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
- while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, (const void**)&record_ptr, &record_size)) == 0) {
- if (is_dgram) {
- sentlen += tnet_sockfd_sendto(socket->wrapped_sock->fd, (const struct sockaddr *)&socket->remote.addr, record_ptr, record_size);
- }
- else {
- sentlen += tnet_socket_send_stream(socket->wrapped_sock, record_ptr, record_size);
- }
- records_len -= (int)record_size;
- records_ptr += record_size;
- }
- TSK_DEBUG_INFO("DTLS data handshake sent len = %d", sentlen);
- }
- }
-
- BIO_reset(socket->rbio);
- BIO_reset(socket->wbio);
-
- if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) {
- TSK_DEBUG_INFO("DTLS handshake completed");
+ tnet_dtls_socket_t *socket = handle;
+ int ret = 0, len;
+ void* out_data;
+
+ if (!socket) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_safeobj_lock(socket);
+
+ // update remote address even if handshaking is completed
+ if (remote_addr) {
+ socket->remote.addr = *remote_addr;
+ }
+
+ if (socket->handshake_completed) {
+ TSK_DEBUG_INFO("Handshake completed");
+ ret = 0;
+ goto bail;
+ }
+
+ if (!socket->handshake_started) {
+ if ((ret = SSL_do_handshake(socket->ssl)) != 1) {
+ switch ((ret = SSL_get_error(socket->ssl, ret))) {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_NONE:
+ break;
+ default:
+ TSK_DEBUG_ERROR("DTLS handshake failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_failed);
+ ret = -2;
+ goto bail;
+ }
+ }
+ socket->handshake_started = (ret == SSL_ERROR_NONE); // TODO: reset for renegotiation
+ }
+
+ if ((len = (int)BIO_get_mem_data(socket->wbio, &out_data)) > 0 && out_data) {
+ if (socket->handshake_storedata) { // e.g. when TURN is enabled we have to query handshaking data and sent it via the negotiated channel
+ if ((int)socket->handshake_data.size < len) {
+ if (!(socket->handshake_data.ptr = tsk_realloc(socket->handshake_data.ptr, len))) {
+ socket->handshake_data.size = 0;
+ socket->handshake_data.count = 0;
+ ret = -5;
+ goto bail;
+ }
+ socket->handshake_data.size = len;
+ }
+ socket->handshake_data.count = len;
+ memcpy(socket->handshake_data.ptr, out_data, len);
+ }
+ else {
+ int sentlen = 0;
+ tnet_port_t port;
+ tnet_ip_t ip;
+ tsk_bool_t is_dgram = TNET_SOCKET_TYPE_IS_DGRAM(socket->wrapped_sock->type);
+ const uint8_t *record_ptr, *records_ptr = out_data;
+ tsk_size_t record_size;
+ int records_len = len;
+
+ tnet_get_sockip_n_port((const struct sockaddr *)&socket->remote.addr, &ip, &port);
+ TSK_DEBUG_INFO("DTLS data handshake to send with len = %d, from(%.*s/%d) to(%.*s/%d)", len, (int)sizeof(socket->wrapped_sock->ip), socket->wrapped_sock->ip, socket->wrapped_sock->port, (int)sizeof(ip), ip, port);
+
+ //!\ IP fragmentation issues must be avoided even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
+ while (records_len > 0 && (ret = tnet_dtls_socket_get_record_first(records_ptr, (tsk_size_t)records_len, (const void**)&record_ptr, &record_size)) == 0) {
+ if (is_dgram) {
+ sentlen += tnet_sockfd_sendto(socket->wrapped_sock->fd, (const struct sockaddr *)&socket->remote.addr, record_ptr, record_size);
+ }
+ else {
+ sentlen += tnet_socket_send_stream(socket->wrapped_sock, record_ptr, record_size);
+ }
+ records_len -= (int)record_size;
+ records_ptr += record_size;
+ }
+ TSK_DEBUG_INFO("DTLS data handshake sent len = %d", sentlen);
+ }
+ }
+
+ BIO_reset(socket->rbio);
+ BIO_reset(socket->wbio);
+
+ if ((socket->handshake_completed = SSL_is_init_finished(socket->ssl))) {
+ TSK_DEBUG_INFO("DTLS handshake completed");
#if HAVE_OPENSSL_DTLS_SRTP
- if (socket->use_srtp){
+ if (socket->use_srtp) {
#if !defined(SRTP_MAX_KEY_LEN)
# define cipher_key_length (128 >> 3) // rfc5764 4.1.2. SRTP Protection Profiles
# define cipher_salt_length (112 >> 3) // rfc5764 4.1.2. SRTP Protection Profiles
- // "cipher_key_length" is also equal to srtp_profile_get_master_key_length(srtp_profile_aes128_cm_sha1_80)
- // "cipher_salt_length" is also srtp_profile_get_master_salt_length(srtp_profile_aes128_cm_sha1_80)
+ // "cipher_key_length" is also equal to srtp_profile_get_master_key_length(srtp_profile_aes128_cm_sha1_80)
+ // "cipher_salt_length" is also srtp_profile_get_master_salt_length(srtp_profile_aes128_cm_sha1_80)
# define SRTP_MAX_KEY_LEN (cipher_key_length + cipher_salt_length)
#endif /* SRTP_MAX_KEY_LEN */
#define EXTRACTOR_dtls_srtp_text "EXTRACTOR-dtls_srtp"
#define EXTRACTOR_dtls_srtp_text_len 19
- uint8_t keying_material[SRTP_MAX_KEY_LEN << 1];
- static const tsk_size_t keying_material_size = sizeof(keying_material);
- /*if(socket->use_srtp)*/{
- SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl);
- if (!p) {
- TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- ret = -2;
- goto bail;
- }
- // alert user
- _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name));
-
- memset(keying_material, 0, sizeof(keying_material));
-
- // rfc5764 - 4.2. Key Derivation
- ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0);
- if (ret != 1) {
- // alert listener
- _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error);
- TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
- ret = -2;
- goto bail;
- }
- }
- // alert listener
- _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_data, keying_material, keying_material_size);
- }
+ uint8_t keying_material[SRTP_MAX_KEY_LEN << 1];
+ static const tsk_size_t keying_material_size = sizeof(keying_material);
+ /*if(socket->use_srtp)*/{
+ SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(socket->ssl);
+ if (!p) {
+ TSK_DEBUG_ERROR("SSL_get_selected_srtp_profile() returned null [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ ret = -2;
+ goto bail;
+ }
+ // alert user
+ _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_profile_selected, p->name, tsk_strlen(p->name));
+
+ memset(keying_material, 0, sizeof(keying_material));
+
+ // rfc5764 - 4.2. Key Derivation
+ ret = SSL_export_keying_material(socket->ssl, keying_material, sizeof(keying_material), EXTRACTOR_dtls_srtp_text, EXTRACTOR_dtls_srtp_text_len, tsk_null, 0, 0);
+ if (ret != 1) {
+ // alert listener
+ _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_error);
+ TSK_DEBUG_ERROR("SSL_export_keying_material() failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
+ ret = -2;
+ goto bail;
+ }
+ }
+ // alert listener
+ _tnet_dtls_socket_raise_event(socket, tnet_dtls_socket_event_type_dtls_srtp_data, keying_material, keying_material_size);
+ }
#endif /* HAVE_OPENSSL_DTLS_SRTP */
- _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed);
- }
- ret = 0; // clear "ret", error will directly jump to "bail:"
+ _tnet_dtls_socket_raise_event_dataless(socket, tnet_dtls_socket_event_type_handshake_succeed);
+ }
+ ret = 0; // clear "ret", error will directly jump to "bail:"
bail:
- tsk_safeobj_unlock(socket);
- return ret;
+ tsk_safeobj_unlock(socket);
+ return ret;
#endif
}
tsk_bool_t tnet_dtls_socket_is_handshake_completed(const tnet_dtls_socket_handle_t* handle)
{
- return (handle && ((const tnet_dtls_socket_t *)handle)->handshake_completed);
+ return (handle && ((const tnet_dtls_socket_t *)handle)->handshake_completed);
}
/*
@@ -678,79 +683,79 @@ Handles DTLS data received over the network using standard functions (e.g. recvf
int tnet_dtls_socket_handle_incoming_data(tnet_dtls_socket_handle_t* handle, const void* data, tsk_size_t size)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
- TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
- return -200;
+ TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
+ return -200;
#else
- tnet_dtls_socket_t *socket = handle;
- int ret = 0;
-
- if (!socket || !data || !size) {
- TSK_DEBUG_ERROR("Invalid parameter");
- return -1;
- }
-
- tsk_safeobj_lock(socket);
-
- TSK_DEBUG_INFO("Receive DTLS data: %lu", (unsigned long)size);
-
- // BIO_reset(socket->rbio);
- // BIO_reset(socket->wbio);
-
- if (!socket->rbio || !socket->wbio) {
- TSK_DEBUG_ERROR("BIO not initialized yet");
- ret = -2;
- goto bail;
- }
-
- if ((ret = _tnet_dtls_socket_do_handshake(socket))) {
- goto bail;
- }
-
- if ((ret = BIO_write(socket->rbio, data, (int)size)) != size) {
- ret = SSL_get_error(socket->ssl, ret);
- TSK_DEBUG_ERROR("BIO_write(rbio, %lu) failed [%s]", (unsigned long)size, ERR_error_string(ERR_get_error(), tsk_null));
- ret = -1;
- goto bail;
- }
-
- /*if((ret = SSL_read(socket->ssl, (void*)data, size)) <= 0){
- switch((ret = SSL_get_error(socket->ssl, ret))){
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_NONE:
- break;
- default:
- {
- unsigned long sslErr = ERR_get_error();
- const uint8_t* pData = (const uint8_t*)data;
- TSK_DEBUG_ERROR("%lu = SSL_read(rbio, %u) failed [%s]", sslErr, size, ERR_error_string(ret, tsk_null));
- // try to understand what's going on
- // rfc6347 - 4.1. Record Layer
- // rfc6347 - 4.2.2. Handshake Message Format
- // rfc6347 - 4.3.2. Handshake Protocol
- if(size > 14 && pData[0] == 0x16){ // content-type=='Handshake'
- if(pData[13] == 0x01 && (socket->setup == tnet_dtls_setup_active || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='client Hello'
- TSK_DEBUG_INFO("DTLS engine was in client mode but we are receiving 'Client Hello' messages. This is a bug in the remote peer: Re-negotiating!");
- tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_passive);
- break;
- }
- else if(pData[13] == 0x02 && (socket->setup == tnet_dtls_setup_passive || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='server Hello'
- TSK_DEBUG_INFO("DTLS engine was in server mode but we are receiving 'Server Hello' messages. This is a bug in the remote peer: Re-negotiating!");
- tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_active);
- break;
- }
- }
- //return -1;
- break;
- }
- }
- }*/
-
- ret = _tnet_dtls_socket_do_handshake(socket);
+ tnet_dtls_socket_t *socket = handle;
+ int ret = 0;
+
+ if (!socket || !data || !size) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ tsk_safeobj_lock(socket);
+
+ TSK_DEBUG_INFO("Receive DTLS data: %lu", (unsigned long)size);
+
+ // BIO_reset(socket->rbio);
+ // BIO_reset(socket->wbio);
+
+ if (!socket->rbio || !socket->wbio) {
+ TSK_DEBUG_ERROR("BIO not initialized yet");
+ ret = -2;
+ goto bail;
+ }
+
+ if ((ret = _tnet_dtls_socket_do_handshake(socket))) {
+ goto bail;
+ }
+
+ if ((ret = BIO_write(socket->rbio, data, (int)size)) != size) {
+ ret = SSL_get_error(socket->ssl, ret);
+ TSK_DEBUG_ERROR("BIO_write(rbio, %lu) failed [%s]", (unsigned long)size, ERR_error_string(ERR_get_error(), tsk_null));
+ ret = -1;
+ goto bail;
+ }
+
+ /*if((ret = SSL_read(socket->ssl, (void*)data, size)) <= 0){
+ switch((ret = SSL_get_error(socket->ssl, ret))){
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_NONE:
+ break;
+ default:
+ {
+ unsigned long sslErr = ERR_get_error();
+ const uint8_t* pData = (const uint8_t*)data;
+ TSK_DEBUG_ERROR("%lu = SSL_read(rbio, %u) failed [%s]", sslErr, size, ERR_error_string(ret, tsk_null));
+ // try to understand what's going on
+ // rfc6347 - 4.1. Record Layer
+ // rfc6347 - 4.2.2. Handshake Message Format
+ // rfc6347 - 4.3.2. Handshake Protocol
+ if(size > 14 && pData[0] == 0x16){ // content-type=='Handshake'
+ if(pData[13] == 0x01 && (socket->setup == tnet_dtls_setup_active || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='client Hello'
+ TSK_DEBUG_INFO("DTLS engine was in client mode but we are receiving 'Client Hello' messages. This is a bug in the remote peer: Re-negotiating!");
+ tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_passive);
+ break;
+ }
+ else if(pData[13] == 0x02 && (socket->setup == tnet_dtls_setup_passive || socket->setup == tnet_dtls_setup_actpass)){ // Handshake Type=='server Hello'
+ TSK_DEBUG_INFO("DTLS engine was in server mode but we are receiving 'Server Hello' messages. This is a bug in the remote peer: Re-negotiating!");
+ tnet_dtls_socket_set_setup(socket, tnet_dtls_setup_active);
+ break;
+ }
+ }
+ //return -1;
+ break;
+ }
+ }
+ }*/
+
+ ret = _tnet_dtls_socket_do_handshake(socket);
bail:
- tsk_safeobj_unlock(socket);
- return ret;
+ tsk_safeobj_unlock(socket);
+ return ret;
#endif
}
@@ -760,47 +765,46 @@ bail:
//
static tsk_object_t* tnet_dtls_socket_ctor(tsk_object_t * self, va_list * app)
{
- tnet_dtls_socket_t *socket = self;
- if (socket){
- tsk_safeobj_init(socket);
- }
- return self;
+ tnet_dtls_socket_t *socket = self;
+ if (socket) {
+ tsk_safeobj_init(socket);
+ }
+ return self;
}
static tsk_object_t* tnet_dtls_socket_dtor(tsk_object_t * self)
{
- tnet_dtls_socket_t *socket = self;
- if (socket){
+ tnet_dtls_socket_t *socket = self;
+ if (socket) {
#if HAVE_OPENSSL
- if (socket->rbio) {
- //BIO_free(socket->rbio);
- socket->rbio = tsk_null;
- }
- if (socket->wbio) {
- //BIO_free(socket->wbio);
- socket->wbio = tsk_null;
- }
- if (socket->ssl) {
- SSL_shutdown(socket->ssl);
- // https://www.openssl.org/docs/crypto/BIO_s_bio.html
- // implicitly frees internal_bio
- SSL_free(socket->ssl);
- }
+ if (socket->rbio) {
+ //BIO_free(socket->rbio);
+ socket->rbio = tsk_null;
+ }
+ if (socket->wbio) {
+ //BIO_free(socket->wbio);
+ socket->wbio = tsk_null;
+ }
+ if (socket->ssl) {
+ SSL_shutdown(socket->ssl);
+ // https://www.openssl.org/docs/crypto/BIO_s_bio.html
+ // implicitly frees internal_bio
+ SSL_free(socket->ssl);
+ }
#endif
- TSK_FREE(socket->handshake_data.ptr);
- TSK_OBJECT_SAFE_FREE(socket->wrapped_sock);
- tsk_safeobj_deinit(socket);
+ TSK_FREE(socket->handshake_data.ptr);
+ TSK_OBJECT_SAFE_FREE(socket->wrapped_sock);
+ tsk_safeobj_deinit(socket);
- TSK_DEBUG_INFO("*** tnet_dtls_socket_t destroyed ***");
- }
- return self;
+ TSK_DEBUG_INFO("*** tnet_dtls_socket_t destroyed ***");
+ }
+ return self;
}
-static const tsk_object_def_t tnet_dtls_socket_def_s =
-{
- sizeof(tnet_dtls_socket_t),
- tnet_dtls_socket_ctor,
- tnet_dtls_socket_dtor,
- tsk_null,
+static const tsk_object_def_t tnet_dtls_socket_def_s = {
+ sizeof(tnet_dtls_socket_t),
+ tnet_dtls_socket_ctor,
+ tnet_dtls_socket_dtor,
+ tsk_null,
};
const tsk_object_def_t *tnet_dtls_socket_def_t = &tnet_dtls_socket_def_s;
OpenPOWER on IntegriCloud