예제 #1
0
파일: Parser.cpp 프로젝트: UIKit0/WebRTC
  bool Parser::extractKeyingMaterial() {

    int r = 0;

    if (!isHandshakeFinished()) {
      printf("dtls::Parser::extractKeyingMaterial()  - error: cannot extract keying material when the handshake isn't finished.\n");
      return false;
    }

    r = SSL_export_keying_material(ssl, 
                                   keying_material, 
                                   DTLS_SRTP_MASTER_LEN * 2,
                                   "EXTRACTOR-dtls_srtp",
                                   19,
                                   NULL, 
                                   0,
                                   0);
  
    if (r != 1) {
      printf("dtls::Parser::extractKeyingMaterial() - error: cannot export the keying material.\n");
      exit(1);
    }

    if (mode == DTLS_MODE_SERVER) {
      /* set the keying material in case we are a server. */
      remote_key = keying_material;
      local_key  = remote_key + DTLS_SRTP_MASTER_KEY_LEN;
      remote_salt = local_key + DTLS_SRTP_MASTER_KEY_LEN;
      local_salt = remote_salt + DTLS_SRTP_MASTER_SALT_LEN;

    }
    else if (mode == DTLS_MODE_CLIENT) {
      printf("dtls::Parser::extractKeyingMaterial() - error: client keying material not tested.\n");
      /* set the keying material in case we are a client. */
      local_key = keying_material;
      remote_key = local_key + DTLS_SRTP_MASTER_KEY_LEN;
      local_salt = remote_key + DTLS_SRTP_MASTER_KEY_LEN;
      remote_salt = local_salt + DTLS_SRTP_MASTER_SALT_LEN;
      exit(1);
    }
    else {
      printf("dtls::Parser::extractKeyingMaterial() - error: unhandled dtls::Parser mode!.\n");
      exit(1);
    }

#if 1
    /* show some debug info (p->name probably = SRTP_AES128_CM_SHA1_80) */
    SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(ssl);
    if(!p) {
      printf("dtls::Parser::extractKeyingMaterial() - error: cannot extract the srtp_profile.\n");
      exit(1);
    }
    printf("dtls::Parser::extractKeyingMaterial() - verbose: protection profile: %s\n", p->name);

    /* cipher probably is AES256-SHA */
    printf("dtls::Parser::extractKeyingMaterial() - verbose: cipher: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(ssl)));
#endif

    return true;
  }
예제 #2
0
static int dlts_netsock_onhandshake_completed(NETIO_SOCK_T *pnetsock) {
  int rc = 0;
  SRTP_PROTECTION_PROFILE *srtpProfile = NULL;
  unsigned char keys[DTLS_SRTP_KEYING_MATERIAL_SIZE];

  if(!(pnetsock->flags & NETIO_FLAG_SRTP)) {
    return 0;
  }

  if(!(srtpProfile = SSL_get_selected_srtp_profile(pnetsock->ssl.pCtxt))) {
    LOG(X_ERROR("DTLS-SRTP SSL_get_selected_srtp_profile failed, peer may not be DTLS-SRTP capable: %s"),
            ERR_reason_error_string(ERR_get_error()));
    return -1;
  }

  memset(keys, 0, sizeof(keys));
  if(SSL_export_keying_material(pnetsock->ssl.pCtxt, keys, sizeof(keys),
                             DTLS_SRTP_KEYS_LABEL, strlen(DTLS_SRTP_KEYS_LABEL), NULL, 0, 0) != 1) {
    LOG(X_ERROR("DTLS-SRTP SSL_export_keying_material failed: %s"),
            ERR_reason_error_string(ERR_get_error()));
    return -1;
  }

  //LOG(X_DEBUG("dlts_netsock_onhandshake_completed DTLS-SRTP handshake selected profile: '%s', master-keys: "), srtpProfile->name); LOGHEX_DEBUG(keys, sizeof(keys));

  if(pnetsock->ssl.dtlsKeysUpdateCtxt.cbKeyUpdateFunc) {
    pnetsock->ssl.dtlsKeysUpdateCtxt.cbKeyUpdateFunc(pnetsock->ssl.dtlsKeysUpdateCtxt.pCbData, pnetsock,
                                                     srtpProfile->name, pnetsock->ssl.dtlsKeysUpdateCtxt.dtls_serverkey,
                                                     pnetsock->ssl.dtlsKeysUpdateCtxt.is_rtcp,
                                                     keys, sizeof(keys));
  }

  return rc;
}
예제 #3
0
	inline
	RTC::SrtpSession::Profile DtlsTransport::GetNegotiatedSrtpProfile()
	{
		MS_TRACE();

		RTC::SrtpSession::Profile negotiated_srtp_profile = RTC::SrtpSession::Profile::NONE;

		// Ensure that the SRTP profile has been negotiated.
		SRTP_PROTECTION_PROFILE* ssl_srtp_profile = SSL_get_selected_srtp_profile(this->ssl);
		if (!ssl_srtp_profile)
		{
			return negotiated_srtp_profile;
		}

		// Get the negotiated SRTP profile.
		for (auto it = DtlsTransport::srtpProfiles.begin(); it != DtlsTransport::srtpProfiles.end(); ++it)
		{
			SrtpProfileMapEntry* profile_entry = &(*it);

			if (std::strcmp(ssl_srtp_profile->name, profile_entry->name) == 0)
			{
				MS_DEBUG("chosen SRTP profile: %s", profile_entry->name);

				negotiated_srtp_profile = profile_entry->profile;
			}
		}

		MS_ASSERT(negotiated_srtp_profile != RTC::SrtpSession::Profile::NONE, "chosen SRTP profile is not an available one");

		return negotiated_srtp_profile;
	}
예제 #4
0
파일: Parser.cpp 프로젝트: UIKit0/WebRTC
  const char* Parser::getCipherSuite() {
    printf("dtls::Parser() - verbose: get cipher suite.\n");
    
    if (!ssl) { return NULL; } 
    if (!isHandshakeFinished()) { return NULL; } 
    
    SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(ssl);
    if (NULL == p) {
      printf("dtls::Parser::getCipherSuite() - cannot extract srtp profile.\n");
      return NULL;
    }

    return p->name;
  }
예제 #5
0
파일: tls_udp.c 프로젝트: brantoco/baresip
static int get_srtp_key_info(const struct dtls_flow *tc, char *name, size_t sz,
			     struct key *client_key, struct key *server_key)
{
	SRTP_PROTECTION_PROFILE *sel;
	const char *keymatexportlabel = "EXTRACTOR-dtls_srtp";
	uint8_t exportedkeymat[1024], *p;
	int keymatexportlen;
	size_t kl = 128, sl = 112;

	sel = SSL_get_selected_srtp_profile(tc->ssl);
	if (!sel)
		return ENOENT;

	str_ncpy(name, sel->name, sz);

	kl /= 8;
	sl /= 8;

	keymatexportlen = (int)(kl + sl)*2;
	if (keymatexportlen != 60) {
		warning("dtls: expected 60 bits, but keying material is %d\n",
			keymatexportlen);
		return EINVAL;
	}

	if (!SSL_export_keying_material(tc->ssl, exportedkeymat,
					keymatexportlen,
					keymatexportlabel,
					strlen(keymatexportlabel),
					NULL, 0, 0)) {
		return ENOENT;
	}

	p = exportedkeymat;

	memcpy(client_key->key,  p, kl); p += kl;
	memcpy(server_key->key,  p, kl); p += kl;
	memcpy(client_key->salt, p, sl); p += sl;
	memcpy(server_key->salt, p, sl); p += sl;

	client_key->key_len  = server_key->key_len  = kl;
	client_key->salt_len = server_key->salt_len = sl;

	return 0;
}
static void export_srtp_keys(ErDtlsConnection *self)
{
    typedef struct {
        guint8 v[SRTP_KEY_LEN];
    } Key;

    typedef struct {
        guint8 v[SRTP_SALT_LEN];
    } Salt;

    struct {
        Key client_key;
        Key server_key;
        Salt client_salt;
        Salt server_salt;
    } exported_keys;

    struct {
        Key key;
        Salt salt;
    } client_key, server_key;

    SRTP_PROTECTION_PROFILE *profile;
    ErDtlsSrtpCipher cipher;
    ErDtlsSrtpAuth auth;
    gint success;

    static gchar export_string[] = "EXTRACTOR-dtls_srtp";

    success = SSL_export_keying_material(self->priv->ssl,
        (gpointer) &exported_keys, 60, export_string, strlen(export_string), NULL, 0, 0);

    if (!success) {
        LOG_WARNING(self, "failed to export srtp keys");
        return;
    }

    profile = SSL_get_selected_srtp_profile(self->priv->ssl);

    LOG_INFO(self, "keys received, profile is %s", profile->name);

    switch (profile->id) {
    case SRTP_AES128_CM_SHA1_80:
        cipher = ER_DTLS_SRTP_CIPHER_AES_128_ICM;
        auth = ER_DTLS_SRTP_AUTH_HMAC_SHA1_80;
        break;
    case SRTP_AES128_CM_SHA1_32:
        cipher = ER_DTLS_SRTP_CIPHER_AES_128_ICM;
        auth = ER_DTLS_SRTP_AUTH_HMAC_SHA1_32;
        break;
    default:
        LOG_WARNING(self, "invalid crypto suite set by handshake");
        goto beach;
    }

    client_key.key = exported_keys.client_key;
    server_key.key = exported_keys.server_key;
    client_key.salt = exported_keys.client_salt;
    server_key.salt = exported_keys.server_salt;

    if (self->priv->is_client) {
        g_signal_emit(self, signals[SIGNAL_ON_ENCODER_KEY], 0, &client_key, cipher, auth);
        g_signal_emit(self, signals[SIGNAL_ON_DECODER_KEY], 0, &server_key, cipher, auth);
    } else {
        g_signal_emit(self, signals[SIGNAL_ON_ENCODER_KEY], 0, &server_key, cipher, auth);
        g_signal_emit(self, signals[SIGNAL_ON_DECODER_KEY], 0, &client_key, cipher, auth);
    }

beach:
    self->priv->keys_exported = TRUE;
}
예제 #7
0
파일: dtls.c 프로젝트: cahlbin/rtpengine
static int dtls_setup_crypto(struct packet_stream *ps, struct dtls_connection *d) {
	const char *err;
	SRTP_PROTECTION_PROFILE *spp;
	int i;
	const struct crypto_suite *cs;
	unsigned char keys[2 * (SRTP_MAX_MASTER_KEY_LEN + SRTP_MAX_MASTER_SALT_LEN)];
	struct crypto_params client, server;

	err = "no SRTP protection profile negotiated";
	spp = SSL_get_selected_srtp_profile(d->ssl);
	if (!spp)
		goto error;

	for (i = 0; i < num_crypto_suites; i++) {
		cs = &crypto_suites[i];
		if (!cs->dtls_name)
			continue;
		if (!strcmp(cs->dtls_name, spp->name))
			goto found;
	}

	err = "unknown SRTP protection profile negotiated";
	goto error;

found:
	i = SSL_export_keying_material(d->ssl, keys, sizeof(keys), "EXTRACTOR-dtls_srtp",
			strlen("EXTRACTOR-dtls_srtp"), NULL, 0, 0);
	err = "failed to export keying material";
	if (i != 1)
		goto error;

	/* got everything XXX except MKI */
	ZERO(client);
	ZERO(server);
	i = 0;

	client.crypto_suite = server.crypto_suite = cs;

	memcpy(client.master_key, &keys[i], cs->master_key_len);
	i += cs->master_key_len;
	memcpy(server.master_key, &keys[i], cs->master_key_len);
	i += cs->master_key_len;
	memcpy(client.master_salt, &keys[i], cs->master_salt_len);
	i += cs->master_salt_len;
	memcpy(server.master_salt, &keys[i], cs->master_salt_len);

	__DBG("SRTP keys negotiated: "
			"c-m: %02x%02x%02x%02x%02x%02x%02x%02x "
			"c-s: %02x%02x%02x%02x%02x%02x%02x%02x "
			"s-m: %02x%02x%02x%02x%02x%02x%02x%02x "
			"s-s: %02x%02x%02x%02x%02x%02x%02x%02x",
			client.master_key[0], client.master_key[1], client.master_key[2], client.master_key[3],
			client.master_key[4], client.master_key[5], client.master_key[6], client.master_key[7],
			client.master_salt[0], client.master_salt[1], client.master_salt[2], client.master_salt[3],
			client.master_salt[4], client.master_salt[5], client.master_salt[6], client.master_salt[7],
			server.master_key[0], server.master_key[1], server.master_key[2], server.master_key[3],
			server.master_key[4], server.master_key[5], server.master_key[6], server.master_key[7],
			server.master_salt[0], server.master_salt[1], server.master_salt[2], server.master_salt[3],
			server.master_salt[4], server.master_salt[5], server.master_salt[6], server.master_salt[7]);

	ilog(LOG_INFO, "DTLS-SRTP successfully negotiated");

	if (d->active) {
		/* we're the client */
		crypto_init(&ps->crypto, &client);
		crypto_init(&ps->sfd->crypto, &server);
	}
	else {
		/* we're the server */
		crypto_init(&ps->crypto, &server);
		crypto_init(&ps->sfd->crypto, &client);
	}

	crypto_dump_keys(&ps->crypto, &ps->sfd->crypto);

	return 0;

error:
	if (!spp)
		ilog(LOG_ERROR, "Failed to set up SRTP after DTLS negotiation: %s", err);
	else
		ilog(LOG_ERROR, "Failed to set up SRTP after DTLS negotiation: %s (profile \"%s\")",
				err, spp->name);
	return -1;
}
예제 #8
0
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;

#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, &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 !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)
#	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);
		}
#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:"
bail:
	tsk_safeobj_unlock(socket);
	return ret;
#endif
}
예제 #9
0
static void
print_stuff(BIO * bio, SSL * s, int full)
{
	X509 *peer = NULL;
	char *p;
	static const char *space = "                ";
	char buf[BUFSIZ];
	STACK_OF(X509) * sk;
	STACK_OF(X509_NAME) * sk2;
	const SSL_CIPHER *c;
	X509_NAME *xn;
	int j, i;
	unsigned char *exportedkeymat;

	if (full) {
		int got_a_chain = 0;

		sk = SSL_get_peer_cert_chain(s);
		if (sk != NULL) {
			got_a_chain = 1;	/* we don't have it for SSL2
						 * (yet) */

			BIO_printf(bio, "---\nCertificate chain\n");
			for (i = 0; i < sk_X509_num(sk); i++) {
				X509_NAME_oneline(X509_get_subject_name(
					sk_X509_value(sk, i)), buf, sizeof buf);
				BIO_printf(bio, "%2d s:%s\n", i, buf);
				X509_NAME_oneline(X509_get_issuer_name(
					sk_X509_value(sk, i)), buf, sizeof buf);
				BIO_printf(bio, "   i:%s\n", buf);
				if (c_showcerts)
					PEM_write_bio_X509(bio, sk_X509_value(sk, i));
			}
		}
		BIO_printf(bio, "---\n");
		peer = SSL_get_peer_certificate(s);
		if (peer != NULL) {
			BIO_printf(bio, "Server certificate\n");
			if (!(c_showcerts && got_a_chain))	/* Redundant if we
								 * showed the whole
								 * chain */
				PEM_write_bio_X509(bio, peer);
			X509_NAME_oneline(X509_get_subject_name(peer),
			    buf, sizeof buf);
			BIO_printf(bio, "subject=%s\n", buf);
			X509_NAME_oneline(X509_get_issuer_name(peer),
			    buf, sizeof buf);
			BIO_printf(bio, "issuer=%s\n", buf);
		} else
			BIO_printf(bio, "no peer certificate available\n");

		sk2 = SSL_get_client_CA_list(s);
		if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0)) {
			BIO_printf(bio, "---\nAcceptable client certificate CA names\n");
			for (i = 0; i < sk_X509_NAME_num(sk2); i++) {
				xn = sk_X509_NAME_value(sk2, i);
				X509_NAME_oneline(xn, buf, sizeof(buf));
				BIO_write(bio, buf, strlen(buf));
				BIO_write(bio, "\n", 1);
			}
		} else {
			BIO_printf(bio, "---\nNo client certificate CA names sent\n");
		}
		p = SSL_get_shared_ciphers(s, buf, sizeof buf);
		if (p != NULL) {
			/*
			 * This works only for SSL 2.  In later protocol
			 * versions, the client does not know what other
			 * ciphers (in addition to the one to be used in the
			 * current connection) the server supports.
			 */

			BIO_printf(bio, "---\nCiphers common between both SSL endpoints:\n");
			j = i = 0;
			while (*p) {
				if (*p == ':') {
					BIO_write(bio, space, 15 - j % 25);
					i++;
					j = 0;
					BIO_write(bio, ((i % 3) ? " " : "\n"), 1);
				} else {
					BIO_write(bio, p, 1);
					j++;
				}
				p++;
			}
			BIO_write(bio, "\n", 1);
		}
		BIO_printf(bio, "---\nSSL handshake has read %ld bytes and written %ld bytes\n",
		    BIO_number_read(SSL_get_rbio(s)),
		    BIO_number_written(SSL_get_wbio(s)));
	}
	BIO_printf(bio, (SSL_cache_hit(s) ? "---\nReused, " : "---\nNew, "));
	c = SSL_get_current_cipher(s);
	BIO_printf(bio, "%s, Cipher is %s\n",
	    SSL_CIPHER_get_version(c),
	    SSL_CIPHER_get_name(c));
	if (peer != NULL) {
		EVP_PKEY *pktmp;
		pktmp = X509_get_pubkey(peer);
		BIO_printf(bio, "Server public key is %d bit\n",
		    EVP_PKEY_bits(pktmp));
		EVP_PKEY_free(pktmp);
	}
	BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
	    SSL_get_secure_renegotiation_support(s) ? "" : " NOT");

	/* Compression is not supported and will always be none. */
	BIO_printf(bio, "Compression: NONE\n");
	BIO_printf(bio, "Expansion: NONE\n");

#ifdef SSL_DEBUG
	{
		/* Print out local port of connection: useful for debugging */
		int sock;
		struct sockaddr_in ladd;
		socklen_t ladd_size = sizeof(ladd);
		sock = SSL_get_fd(s);
		getsockname(sock, (struct sockaddr *) & ladd, &ladd_size);
		BIO_printf(bio_c_out, "LOCAL PORT is %u\n", ntohs(ladd.sin_port));
	}
#endif

#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
	if (next_proto.status != -1) {
		const unsigned char *proto;
		unsigned int proto_len;
		SSL_get0_next_proto_negotiated(s, &proto, &proto_len);
		BIO_printf(bio, "Next protocol: (%d) ", next_proto.status);
		BIO_write(bio, proto, proto_len);
		BIO_write(bio, "\n", 1);
	}
#endif

#ifndef OPENSSL_NO_SRTP
	{
		SRTP_PROTECTION_PROFILE *srtp_profile = SSL_get_selected_srtp_profile(s);

		if (srtp_profile)
			BIO_printf(bio, "SRTP Extension negotiated, profile=%s\n",
			    srtp_profile->name);
	}
#endif

	SSL_SESSION_print(bio, SSL_get_session(s));
	if (keymatexportlabel != NULL) {
		BIO_printf(bio, "Keying material exporter:\n");
		BIO_printf(bio, "    Label: '%s'\n", keymatexportlabel);
		BIO_printf(bio, "    Length: %i bytes\n", keymatexportlen);
		exportedkeymat = malloc(keymatexportlen);
		if (exportedkeymat != NULL) {
			if (!SSL_export_keying_material(s, exportedkeymat,
				keymatexportlen,
				keymatexportlabel,
				strlen(keymatexportlabel),
				NULL, 0, 0)) {
				BIO_printf(bio, "    Error\n");
			} else {
				BIO_printf(bio, "    Keying material: ");
				for (i = 0; i < keymatexportlen; i++)
					BIO_printf(bio, "%02X",
					    exportedkeymat[i]);
				BIO_printf(bio, "\n");
			}
			free(exportedkeymat);
		}
	}
	BIO_printf(bio, "---\n");
	if (peer != NULL)
		X509_free(peer);
	/* flush, or debugging output gets mixed with http response */
	(void) BIO_flush(bio);
}
예제 #10
0
int krx_udp_receive(udp_conn* c) {

  socklen_t len = sizeof(c->client);
  ssize_t nread = recvfrom(c->sock, c->buf, KRX_UDP_BUF_LEN, 0, (struct sockaddr*)&c->client, &len);

  if(nread < 0) {
    printf("Error: cannot receive.\n");
    return -1;
  }
  if(nread < 2) { 
    printf("Only received 2 bytes?\n");
    return 0;
  }

  if((c->buf[0] == 0x00 || c->buf[0] == 0x01) && (c->buf[1] == 0x00 || c->buf[1] == 0x01) ) {
    handle_stun(c, c->buf, nread);
  }
  else {
    if(krx_dtls_is_handshake_done(&c->dtls) > 0) {
      if(c->state == KRX_STATE_NONE) {
        // when done, we pass on the data libsrtp

        c->state = KRX_STATE_SSL_INIT_READY;
        printf("---------------------- finished --------------------------\n");
        uint8_t material[KRX_SRTP_MASTER_LEN * 2];
        int r = SSL_export_keying_material(c->dtls.ssl, material, KRX_SRTP_MASTER_LEN * 2, 
                                           "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0);

        if(r == 0) {
          printf("Error: cannot export the SSL keying material.\n");
          exit(EXIT_FAILURE);
        }
        
        // extracking keying example https://github.com/traviscross/baresip/blob/8974d662c942b10a9bb05223ddc7881896dd4c2f/modules/dtls_srtp/tls_udp.c
        /* Keys:: http://tools.ietf.org/html/rfc5764#section-4.2, note: client <> server use different keying, we handle server for now. */
        uint8_t* remote_key = material;
        uint8_t* local_key = remote_key + KRX_SRTP_MASTER_KEY_LEN;
        uint8_t* remote_salt = local_key + KRX_SRTP_MASTER_KEY_LEN;
        uint8_t* local_salt = remote_salt + KRX_SRTP_MASTER_SALT_LEN;;

        memcpy(c->srtp.policy.key, remote_key, KRX_SRTP_MASTER_KEY_LEN);
        memcpy(c->srtp.policy.key + KRX_SRTP_MASTER_KEY_LEN, remote_salt, KRX_SRTP_MASTER_SALT_LEN);

        SRTP_PROTECTION_PROFILE *p = SSL_get_selected_srtp_profile(c->dtls.ssl);
        if(!p) {
          printf("Error: cannot extract the srtp_profile.\n");
          exit(EXIT_FAILURE);
        }
        printf(">>>>>>> %s <<<<<\n", p->name);

        // TLS_RSA_WITH_AES_128_CBC_SHA 
        printf("---> cipher: %s\n", SSL_CIPHER_get_name(SSL_get_current_cipher(c->dtls.ssl)));


        /* create SRTP session */
        err_status_t sr = srtp_create(&c->srtp.session, &c->srtp.policy);
        if(sr != err_status_ok) {
          printf("Error: cannot create srtp session: %d.\n", sr);
          exit(EXIT_FAILURE);
        }

        /* @TODO --- CLEANUP! - WE NEED TO UNPROTECT THIS DIRECTLY!!!  SEE "MARKER-MARKER" below*/
        int buflen = nread;
        sr = srtp_unprotect(c->srtp.session, c->buf, &buflen);
        
        if(sr != err_status_ok) {
          printf("Error: cannot unprotect, err: %d. len: %d <> %d\n", sr, len, buflen);
        }
        else {
          //printf("~ %zd bytes read // buflen: %d.\n", nread, buflen);
          krx_rtp_decode(&c->rtp, c->buf, buflen);
        }

      }
      else if(c->state == KRX_STATE_SSL_INIT_READY) {
        /* @TODO --- CLEANUP! duplicate, see a couple of line above */
        /* MARKER-MARKER */
        int buflen = nread;
        err_status_t sr = srtp_unprotect(c->srtp.session, c->buf, &buflen);
        
        if(sr != err_status_ok) {
          printf("Error: cannot unprotect, err: %d. len: %d <> %d\n", sr, len, buflen);
        }
        else {
          //printf("~ %zd bytes read // buflen: %d.\n", nread, buflen);
          krx_rtp_decode(&c->rtp, c->buf, buflen);
        }

      }
      
    }
    else {
      krx_dtls_handle_traffic(&c->dtls, c->buf, nread);
    }
  }
  return 0;
}
예제 #11
0
void janus_dtls_srtp_incoming_msg(janus_dtls_srtp *dtls, char *buf, uint16_t len) {
	if(dtls == NULL) {
		JANUS_LOG(LOG_ERR, "No DTLS-SRTP stack, no incoming message...\n");
		return;
	}
	janus_ice_component *component = (janus_ice_component *)dtls->component;
	if(component == NULL) {
		JANUS_LOG(LOG_ERR, "No component, no DTLS...\n");
		return;
	}
	janus_ice_stream *stream = component->stream;
	if(!stream) {
		JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n");
		return;
	}
	janus_ice_handle *handle = stream->handle;
	if(!handle || !handle->agent) {
		JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n");
		return;
	}
	if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT)) {
		JANUS_LOG(LOG_WARN, "[%"SCNu64"] Alert already triggered, clearing up...\n", handle->handle_id);
		return;
	}
	if(!dtls->ssl || !dtls->read_bio) {
		JANUS_LOG(LOG_ERR, "[%"SCNu64"] No DTLS stuff for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
		return;
	}
	if(dtls->dtls_started == 0) {
		/* Handshake not started yet: maybe we're still waiting for the answer and the DTLS role? */
		return;
	}
	janus_dtls_fd_bridge(dtls);
	int written = BIO_write(dtls->read_bio, buf, len);
	if(written != len) {
		JANUS_LOG(LOG_WARN, "[%"SCNu64"]     Only written %d/%d of those bytes on the read BIO...\n", handle->handle_id, written, len);
	} else {
		JANUS_LOG(LOG_HUGE, "[%"SCNu64"]     Written %d bytes on the read BIO...\n", handle->handle_id, written);
	}
	janus_dtls_fd_bridge(dtls);
	/* Try to read data */
	char data[1500];	/* FIXME */
	memset(&data, 0, 1500);
	int read = SSL_read(dtls->ssl, &data, 1500);
	JANUS_LOG(LOG_HUGE, "[%"SCNu64"]     ... and read %d of them from SSL...\n", handle->handle_id, read);
	if(read < 0) {
		unsigned long err = SSL_get_error(dtls->ssl, read);
		if(err == SSL_ERROR_SSL) {
			/* Ops, something went wrong with the DTLS handshake */
			char error[200];
			ERR_error_string_n(ERR_get_error(), error, 200);
			JANUS_LOG(LOG_ERR, "[%"SCNu64"] Handshake error: %s\n", handle->handle_id, error);
			return;
		}
	}
	janus_dtls_fd_bridge(dtls);
	if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_STOP) || janus_is_stopping()) {
		/* DTLS alert triggered, we should end it here */
		JANUS_LOG(LOG_VERB, "[%"SCNu64"] Forced to stop it here...\n", handle->handle_id);
		return;
	}
	if(!SSL_is_init_finished(dtls->ssl)) {
		/* Nothing else to do for now */
		JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Initialization not finished yet...\n", handle->handle_id);
		return;
	}
	if(dtls->ready) {
		/* There's data to be read? */
		JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Any data available?\n", handle->handle_id);
#ifdef HAVE_SCTP
		if(dtls->sctp != NULL && read > 0) {
			JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Sending data (%d bytes) to the SCTP stack...\n", handle->handle_id, read);
			janus_sctp_data_from_dtls(dtls->sctp, data, read);
		}
#else
		if(read > 0) {
			JANUS_LOG(LOG_WARN, "[%"SCNu64"] Data available but Data Channels support disabled...\n", handle->handle_id);
		}
#endif
	} else {
		JANUS_LOG(LOG_VERB, "[%"SCNu64"] DTLS established, yay!\n", handle->handle_id);
		/* Check the remote fingerprint */
		X509 *rcert = SSL_get_peer_certificate(dtls->ssl);
		if(!rcert) {
			JANUS_LOG(LOG_ERR, "[%"SCNu64"] No remote certificate?? (%s)\n",
				handle->handle_id, ERR_reason_error_string(ERR_get_error()));
		} else {
			unsigned int rsize;
			unsigned char rfingerprint[EVP_MAX_MD_SIZE];
			char remote_fingerprint[160];
			char *rfp = (char *)&remote_fingerprint;
			if(stream->remote_hashing && !strcasecmp(stream->remote_hashing, "sha-1")) {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-1 fingerprint of remote certificate...\n", handle->handle_id);
				X509_digest(rcert, EVP_sha1(), (unsigned char *)rfingerprint, &rsize);
			} else {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Computing sha-256 fingerprint of remote certificate...\n", handle->handle_id);
				X509_digest(rcert, EVP_sha256(), (unsigned char *)rfingerprint, &rsize);
			}
			X509_free(rcert);
			rcert = NULL;
			unsigned int i = 0;
			for(i = 0; i < rsize; i++) {
				g_snprintf(rfp, 4, "%.2X:", rfingerprint[i]);
				rfp += 3;
			}
			*(rfp-1) = 0;
			JANUS_LOG(LOG_VERB, "[%"SCNu64"] Remote fingerprint (%s) of the client is %s\n",
				handle->handle_id, stream->remote_hashing ? stream->remote_hashing : "sha-256", remote_fingerprint);
			if(!strcasecmp(remote_fingerprint, stream->remote_fingerprint ? stream->remote_fingerprint : "(none)")) {
				JANUS_LOG(LOG_VERB, "[%"SCNu64"]  Fingerprint is a match!\n", handle->handle_id);
				dtls->dtls_state = JANUS_DTLS_STATE_CONNECTED;
				dtls->dtls_connected = janus_get_monotonic_time();
				/* Notify event handlers */
				janus_dtls_notify_state_change(dtls);
			} else {
				/* FIXME NOT a match! MITM? */
				JANUS_LOG(LOG_ERR, "[%"SCNu64"]  Fingerprint is NOT a match! got %s, expected %s\n", handle->handle_id, remote_fingerprint, stream->remote_fingerprint);
				dtls->dtls_state = JANUS_DTLS_STATE_FAILED;
				/* Notify event handlers */
				janus_dtls_notify_state_change(dtls);
				goto done;
			}
			if(dtls->dtls_state == JANUS_DTLS_STATE_CONNECTED) {
				/* Which SRTP profile is being negotiated? */
				SRTP_PROTECTION_PROFILE *srtp_profile = SSL_get_selected_srtp_profile(dtls->ssl);
				if(srtp_profile == NULL) {
					/* Should never happen, but just in case... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] No SRTP profile selected...\n", handle->handle_id);
					dtls->dtls_state = JANUS_DTLS_STATE_FAILED;
					/* Notify event handlers */
					janus_dtls_notify_state_change(dtls);
					goto done;
				}
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] %s\n", handle->handle_id, srtp_profile->name);
				int key_length = 0, salt_length = 0, master_length = 0;
				switch(srtp_profile->id) {
					case SRTP_AES128_CM_SHA1_80:
					case SRTP_AES128_CM_SHA1_32:
						key_length = SRTP_MASTER_KEY_LENGTH;
						salt_length = SRTP_MASTER_SALT_LENGTH;
						master_length = SRTP_MASTER_LENGTH;
						break;
#ifdef HAVE_SRTP_AESGCM
					case SRTP_AEAD_AES_256_GCM:
						key_length = SRTP_AESGCM256_MASTER_KEY_LENGTH;
						salt_length = SRTP_AESGCM256_MASTER_SALT_LENGTH;
						master_length = SRTP_AESGCM256_MASTER_LENGTH;
						break;
					case SRTP_AEAD_AES_128_GCM:
						key_length = SRTP_AESGCM128_MASTER_KEY_LENGTH;
						salt_length = SRTP_AESGCM128_MASTER_SALT_LENGTH;
						master_length = SRTP_AESGCM128_MASTER_LENGTH;
						break;
#endif
					default:
						/* Will never happen? */
						JANUS_LOG(LOG_WARN, "[%"SCNu64"] Unsupported SRTP profile %lu\n", handle->handle_id, srtp_profile->id);
						break;
				}
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Key/Salt/Master: %d/%d/%d\n",
					handle->handle_id, master_length, key_length, salt_length);
				/* Complete with SRTP setup */
				unsigned char material[master_length*2];
				unsigned char *local_key, *local_salt, *remote_key, *remote_salt;
				/* Export keying material for SRTP */
				if(!SSL_export_keying_material(dtls->ssl, material, master_length*2, "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
					/* Oops... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, couldn't extract SRTP keying material for component %d in stream %d?? (%s)\n",
						handle->handle_id, component->component_id, stream->stream_id, ERR_reason_error_string(ERR_get_error()));
					goto done;
				}
				/* Key derivation (http://tools.ietf.org/html/rfc5764#section-4.2) */
				if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) {
					local_key = material;
					remote_key = local_key + key_length;
					local_salt = remote_key + key_length;
					remote_salt = local_salt + salt_length;
				} else {
					remote_key = material;
					local_key = remote_key + key_length;
					remote_salt = local_key + key_length;
					local_salt = remote_salt + salt_length;
				}
				/* Build master keys and set SRTP policies */
					/* Remote (inbound) */
				switch(srtp_profile->id) {
					case SRTP_AES128_CM_SHA1_80:
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(dtls->remote_policy.rtp));
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(dtls->remote_policy.rtcp));
						break;
					case SRTP_AES128_CM_SHA1_32:
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&(dtls->remote_policy.rtp));
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(dtls->remote_policy.rtcp));
						break;
#ifdef HAVE_SRTP_AESGCM
					case SRTP_AEAD_AES_256_GCM:
						srtp_crypto_policy_set_aes_gcm_256_16_auth(&(dtls->remote_policy.rtp));
						srtp_crypto_policy_set_aes_gcm_256_16_auth(&(dtls->remote_policy.rtcp));
						break;
					case SRTP_AEAD_AES_128_GCM:
						srtp_crypto_policy_set_aes_gcm_128_16_auth(&(dtls->remote_policy.rtp));
						srtp_crypto_policy_set_aes_gcm_128_16_auth(&(dtls->remote_policy.rtcp));
						break;
#endif
					default:
						/* Will never happen? */
						JANUS_LOG(LOG_WARN, "[%"SCNu64"] Unsupported SRTP profile %s\n", handle->handle_id, srtp_profile->name);
						break;
				}
				dtls->remote_policy.ssrc.type = ssrc_any_inbound;
				unsigned char remote_policy_key[master_length];
				dtls->remote_policy.key = (unsigned char *)&remote_policy_key;
				memcpy(dtls->remote_policy.key, remote_key, key_length);
				memcpy(dtls->remote_policy.key + key_length, remote_salt, salt_length);
#if HAS_DTLS_WINDOW_SIZE
				dtls->remote_policy.window_size = 128;
				dtls->remote_policy.allow_repeat_tx = 0;
#endif
				dtls->remote_policy.next = NULL;
					/* Local (outbound) */
				switch(srtp_profile->id) {
					case SRTP_AES128_CM_SHA1_80:
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(dtls->local_policy.rtp));
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(dtls->local_policy.rtcp));
						break;
					case SRTP_AES128_CM_SHA1_32:
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(&(dtls->local_policy.rtp));
						srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(&(dtls->local_policy.rtcp));
						break;
#ifdef HAVE_SRTP_AESGCM
					case SRTP_AEAD_AES_256_GCM:
						srtp_crypto_policy_set_aes_gcm_256_16_auth(&(dtls->local_policy.rtp));
						srtp_crypto_policy_set_aes_gcm_256_16_auth(&(dtls->local_policy.rtcp));
						break;
					case SRTP_AEAD_AES_128_GCM:
						srtp_crypto_policy_set_aes_gcm_128_16_auth(&(dtls->local_policy.rtp));
						srtp_crypto_policy_set_aes_gcm_128_16_auth(&(dtls->local_policy.rtcp));
						break;
#endif
					default:
						/* Will never happen? */
						JANUS_LOG(LOG_WARN, "[%"SCNu64"] Unsupported SRTP profile %s\n", handle->handle_id, srtp_profile->name);
						break;
				}
				dtls->local_policy.ssrc.type = ssrc_any_outbound;
				unsigned char local_policy_key[master_length];
				dtls->local_policy.key = (unsigned char *)&local_policy_key;
				memcpy(dtls->local_policy.key, local_key, key_length);
				memcpy(dtls->local_policy.key + key_length, local_salt, salt_length);
#if HAS_DTLS_WINDOW_SIZE
				dtls->local_policy.window_size = 128;
				dtls->local_policy.allow_repeat_tx = 0;
#endif
				dtls->local_policy.next = NULL;
				/* Create SRTP sessions */
				srtp_err_status_t res = srtp_create(&(dtls->srtp_in), &(dtls->remote_policy));
				if(res != srtp_err_status_ok) {
					/* Something went wrong... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating inbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
					JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_srtp_error_str(res));
					goto done;
				}
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created inbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
				res = srtp_create(&(dtls->srtp_out), &(dtls->local_policy));
				if(res != srtp_err_status_ok) {
					/* Something went wrong... */
					JANUS_LOG(LOG_ERR, "[%"SCNu64"] Oops, error creating outbound SRTP session for component %d in stream %d??\n", handle->handle_id, component->component_id, stream->stream_id);
					JANUS_LOG(LOG_ERR, "[%"SCNu64"]  -- %d (%s)\n", handle->handle_id, res, janus_srtp_error_str(res));
					goto done;
				}
				dtls->srtp_profile = srtp_profile->id;
				dtls->srtp_valid = 1;
				JANUS_LOG(LOG_VERB, "[%"SCNu64"] Created outbound SRTP session for component %d in stream %d\n", handle->handle_id, component->component_id, stream->stream_id);
#ifdef HAVE_SCTP
				if(janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_DATA_CHANNELS)) {
					/* Create SCTP association as well */
					janus_dtls_srtp_create_sctp(dtls);
				}
#endif
				dtls->ready = 1;
			}
done:
			if(!janus_flags_is_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_ALERT) && dtls->srtp_valid) {
				/* Handshake successfully completed */
				janus_ice_dtls_handshake_done(handle, component);
			} else {
				/* Something went wrong in either DTLS or SRTP... tell the plugin about it */
				janus_dtls_callback(dtls->ssl, SSL_CB_ALERT, 0);
				janus_flags_set(&handle->webrtc_flags, JANUS_ICE_HANDLE_WEBRTC_CLEANING);
			}
		}
	}
}