MILESTONE: dtls-srtp inbound

This commit is contained in:
Anthony Minessale 2013-02-01 20:07:56 -06:00
parent dabb85c3f6
commit dd9271d6b9
3 changed files with 101 additions and 27 deletions

View File

@ -60,6 +60,7 @@ typedef enum {
NO_CRYPTO,
AES_CM_128_HMAC_SHA1_80,
AES_CM_128_HMAC_SHA1_32,
AES_CM_256_HMAC_SHA1_80,
AES_CM_128_NULL_AUTH
} switch_rtp_crypto_key_type_t;

View File

@ -3695,7 +3695,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
if (!zstr(a_engine->local_dtls_fingerprint.str)) {
dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_SERVER : DTLS_TYPE_CLIENT;
dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_CLIENT;
dtype |= DTLS_TYPE_RTP;
if (a_engine->rtcp_mux > 0) dtype |= DTLS_TYPE_RTCP;

View File

@ -54,6 +54,8 @@
#include <openssl/err.h>
#include <openssl/bio.h>
#define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++
#define READ_DEC(rtp_session) switch_mutex_unlock(rtp_session->read_mutex); rtp_session->reading--
#define WRITE_INC(rtp_session) switch_mutex_lock(rtp_session->write_mutex); rtp_session->writing++
@ -198,6 +200,7 @@ typedef struct switch_dtls_s {
switch_sockaddr_t *remote_addr;
char *rsa;
char *pvt;
char *ca;
struct switch_rtp *rtp_session;
} switch_dtls_t;
@ -1320,7 +1323,6 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
goto end;
} else {
//printf("XXXXXXXXXXXXXXXXWTF1 PROTECT RTCP %ld->%d bytes %d\n", rtcp_bytes, sbytes, rtp_session->rtcp_interval);
rtcp_bytes = sbytes;
}
@ -1938,20 +1940,71 @@ static const char *dtls_state_names(dtls_state_t s)
static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
/// duhhh
return -1;
}
#define cr_keylen 16
#define cr_saltlen 14
#define cr_kslen 30
static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
X509 *cert;
int r = 0;
if ((cert = SSL_get_peer_certificate(dtls->ssl))) {
switch_core_cert_extract_fingerprint(cert, dtls->remote_fp);
r = switch_core_cert_verify(dtls->remote_fp);
X509_free(cert);
}
if (!r) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Fingerprint Verification Failed!.\n");
dtls_set_state(dtls, DS_FAIL);
return -1;
} else {
uint8_t raw_key_data[cr_kslen*2] = { 0 };
unsigned char *local_key, *remote_key, *local_salt, *remote_salt;
unsigned char local_key_buf[cr_kslen] = {0}, remote_key_buf[cr_kslen] = {0};
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Fingerprint Verified.\n");
if (!SSL_export_keying_material(dtls->ssl, raw_key_data, sizeof(raw_key_data), "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Key material export failure\n");
dtls_set_state(dtls, DS_FAIL);
return -1;
}
if ((dtls->type & DTLS_TYPE_CLIENT)) {
local_key = raw_key_data;
remote_key = local_key + cr_keylen;
local_salt = remote_key + cr_keylen;
remote_salt = local_salt + cr_saltlen;
} else {
remote_key = raw_key_data;
local_key = remote_key + cr_keylen;
remote_salt = local_key + cr_keylen;
local_salt = remote_salt + cr_saltlen;
}
memcpy(local_key_buf, local_key, cr_keylen);
memcpy(local_key_buf + cr_keylen, local_salt, cr_saltlen);
memcpy(remote_key_buf, remote_key, cr_keylen);
memcpy(remote_key_buf + cr_keylen, remote_salt, cr_saltlen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_SEND, 0, AES_CM_128_HMAC_SHA1_80, local_key_buf, cr_kslen);
switch_rtp_add_crypto_key(rtp_session, SWITCH_RTP_CRYPTO_RECV, 0, AES_CM_128_HMAC_SHA1_80, remote_key_buf, cr_kslen);
}
dtls_set_state(dtls, DS_READY);
return 0;
}
static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
{
printf("ready...\n");
return 0;
}
@ -1985,11 +2038,7 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
void *data;
switch_size_t bytes;
//printf("WTF %s...\n", dtls_state_names(dtls->state));
if (dtls->bytes) {
printf("READ %ld\n", dtls->bytes);
if ((ret = BIO_write(dtls->read_bio, dtls->data, dtls->bytes)) != dtls->bytes) {
ret = SSL_get_error(dtls->ssl, ret);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS packet read err %d\n", ret);
@ -2001,12 +2050,13 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
if (SSL_read(dtls->ssl, dtls->data, dtls->bytes) == dtls->bytes) {
if (BIO_reset(dtls->read_bio));
}
r = dtls_states[dtls->state](rtp_session, dtls);
if ((len = BIO_get_mem_data(dtls->write_bio, &data)) && data) {
bytes = len;
printf("WRITE %ld\n", bytes);
if (switch_socket_sendto(dtls->sock_output, dtls->remote_addr, 0, data, &bytes ) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS packet not written\n");
} else {
@ -2014,12 +2064,10 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
}
}
return r;
}
#if VERIFY
static int cb_verify_peer(int preverify_ok, X509_STORE_CTX *ctx)
{
SSL *ssl = NULL;
@ -2034,8 +2082,6 @@ static int cb_verify_peer(int preverify_ok, X509_STORE_CTX *ctx)
return 0;
}
printf("OMFG?!!!!\n");
if ((cert = SSL_get_peer_certificate(dtls->ssl))) {
switch_core_cert_extract_fingerprint(cert, dtls->remote_fp);
@ -2048,10 +2094,12 @@ static int cb_verify_peer(int preverify_ok, X509_STORE_CTX *ctx)
return r;
}
#endif
SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type)
{
switch_dtls_t *dtls;
int ret;
if (!switch_rtp_ready(rtp_session)) {
return SWITCH_STATUS_FALSE;
@ -2067,15 +2115,20 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
dtls->pvt = switch_core_sprintf(rtp_session->pool, "%s%s%s.key", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
dtls->rsa = switch_core_sprintf(rtp_session->pool, "%s%s%s.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR, DTLS_SRTP_FNAME);
//dtls->ca = switch_core_sprintf(rtp_session->pool, "%s%sca-bundle.crt", SWITCH_GLOBAL_dirs.certs_dir, SWITCH_PATH_SEPARATOR);
dtls->ssl_ctx = SSL_CTX_new(DTLSv1_method());
switch_assert(dtls->ssl_ctx);
SSL_CTX_set_mode(dtls->ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
//SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_cipher_list(dtls->ssl_ctx, "ALL");
SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32");
//SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32");
SSL_CTX_set_tlsext_use_srtp(dtls->ssl_ctx, "SRTP_AES128_CM_SHA1_80");
dtls->type = type;
dtls->read_bio = BIO_new(BIO_s_mem());
@ -2087,15 +2140,34 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
BIO_set_mem_eof_return(dtls->read_bio, -1);
BIO_set_mem_eof_return(dtls->write_bio, -1);
SSL_CTX_use_certificate_file(dtls->ssl_ctx, dtls->rsa, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(dtls->ssl_ctx, dtls->pvt, SSL_FILETYPE_PEM);
if ((ret=SSL_CTX_use_certificate_file(dtls->ssl_ctx, dtls->rsa, SSL_FILETYPE_PEM)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS cert err [%d]\n", SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
if ((ret=SSL_CTX_use_PrivateKey_file(dtls->ssl_ctx, dtls->pvt, SSL_FILETYPE_PEM)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS key err [%d]\n", SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
if (SSL_CTX_check_private_key(dtls->ssl_ctx) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS check key failed\n");
return SWITCH_STATUS_FALSE;
}
if (!zstr(dtls->ca) && (ret=SSL_CTX_load_verify_locations(dtls->ssl_ctx, dtls->ca, NULL)) != 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS check chain cert failed [%d]\n",
SSL_get_error(dtls->ssl, ret));
return SWITCH_STATUS_FALSE;
}
dtls->ssl = SSL_new(dtls->ssl_ctx);
SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
SSL_set_mode(dtls->ssl, SSL_MODE_AUTO_RETRY);
SSL_set_read_ahead(dtls->ssl, 1);
SSL_set_verify(dtls->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), cb_verify_peer);
//SSL_set_verify(dtls->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), cb_verify_peer);
SSL_set_verify(dtls->ssl, SSL_VERIFY_NONE, NULL);
SSL_set_app_data(dtls->ssl, dtls);
dtls->local_fp = local_fp;
@ -2189,6 +2261,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
switch_channel_set_variable(channel, "sip_has_crypto", "AES_CM_128_HMAC_SHA1_32");
}
break;
case AES_CM_256_HMAC_SHA1_80:
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy->rtp);
crypto_policy_set_aes_cm_256_hmac_sha1_80(&policy->rtcp);
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_set_variable(channel, "sip_has_crypto", "AES_CM_256_HMAC_SHA1_80");
}
case AES_CM_128_NULL_AUTH:
crypto_policy_set_aes_cm_128_null_auth(&policy->rtp);
crypto_policy_set_aes_cm_128_null_auth(&policy->rtcp);
@ -2396,9 +2475,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
rtp_session->payload = payload;
rtp_session->rpayload = payload;
switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval);
rtp_session->conf_samples_per_interval = samples_per_interval;
@ -4104,8 +4180,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
}
rtcp_bytes = sbytes;
//printf("XXXXXXXXXXXXXXXXWTF2 PROTECT RTCP %d bytes\n", sbytes);
}
#endif
@ -5019,7 +5093,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP protection failed with code %d\n", stat);
}
//printf("XXXXXXXXXXXXXXXXWTF PROTECT RTP %d bytes\n", sbytes);
bytes = sbytes;
}
#endif
@ -5420,7 +5494,6 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session,
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP protection failed with code %d\n", stat);
}
bytes = sbytes;
//printf("XXXXXXXXXXXXXXXXWTF PROTECT RTP %d bytes\n", sbytes);
}
#endif
#ifdef ENABLE_ZRTP