Native Webrtc how to disable encryption for DataChannel of PeerConnection - encryption

I am currently working on within a project which is trying to build a communication adapter for the old game Supreme Commander. This communication adapter uses native webrtc. The project is Forged Alliance Forever and this is the repositoy for the communication adapter: github.com/FAForever/ice-adapter
The communication adapter is currently working with encrypted communication, but we would like to disable encryption. Upload Bandwidth is a limiting factor in games with many participants and DTLS adds overhead to each message. Those messages have a little size of around 20-50 bytes. Therefore overhead of the DTLS header and padding are significant.
So here is the question:
Is it possible to disable encryption for the DataChannel of a PeerConnection using the native webrtc release 68?
If so, how? Do you have a minimal example?
I tried the following things (sorry for code snippets):
Create PeerConnectionFactory and disable encryption in the options:
_pcfactory = webrtc::CreateModularPeerConnectionFactory(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
webrtc::PeerConnectionFactoryInterface::Options webRtcOptions;
webRtcOptions.disable_encryption = true;
_pcfactory->SetOptions(webRtcOptions);
Create the PeerConnection with enable rtp data channel:
webrtc::PeerConnectionInterface::RTCConfiguration configuration;
configuration.servers = _iceServerList;
configuration.enable_rtp_data_channel = true;
_peerConnection = _pcfactory->CreatePeerConnection(configuration,nullptr, nullptr, _peerConnectionObserverObj);
This is so far what I have tested. The problem is now, that the answerer side produces an abort in channel.cc, so maybe i did not use the interface correctly. Do you have any suggestions?
Regards

You can set the DtlsSrtpKeyAgreement contraint to false when creating the peerconnection. However, this option may be removed soon from the library, see https://bugs.chromium.org/p/chromium/issues/detail?id=804275
but the neccessary code changes will remain in git anyways, therefore you can re-enable that option by reverting that change before compiling the library.

Related

How do I tell if my BLE communication use asymmetric encryption, if encrypted at all? (BLE 5.x)

I want to know if my BLE 5 (low energy, not "typical"/core bluetooth) embedded system uses (preferably asymmetric) encryption, if encrypted at all.
I'm using this ble module that is communicating with an SOC. My SOC is capable of encryption but the FAE of the BLE module product couldn't come up with any useful information.
My program doesn't appear to have a bonding/pairing process, but I could be wrong since I did not take a closer look at the HAL layer program.
My question is, does BLE 5 require encryption?
If not, how do I find out if my connection is encrypted or not, using methods other than sniffers? For example are there any steps which must be gone through to facilitate encryption, in which case I should check if these steps were skipped or not? (If skipped then surely my communication is in plain texts).
ETA: The target BLE module is based on nrf52832, don't know what BLE stack/softdevice they are using. My soc is STM32WB55 series, using a rather comprehensive BLE stack that supports most functions of which name I couldn't recall for the moment.
BLE does not require encryption for a connection to be made.
At first, every BLE connection starts in Security Mode 1, Level 1 which does not use any encryption at all. Every message will be sent in cleartext. To increase the security two devices have to "pair". Security keys are exchange during the pairing process. There are multiple different pairing methods with different requirements. Have a look at this article for a starting point.
The pairing process is usually not started manually but automatically as soon as a device tries to access a secured characteristic. If you are using a phone to access such a characteristic you will be prompted with a pairing request popup. Based on your description I would assume that your connection is currently not encrypted.
To enable encryption on your SoC please have a look at the function aci_gatt_add_char. This document (direct download link) refers to this function on page 55 and shows that it takes Security_Permissions as an argument. The next page states the possible options as:
0x00: ATTR_PERMISSION_NONE
0x01: Need authentication to read
0x02: Need authorization to read
0x04: Link should be encrypted to read
0x08: Need authentication to write
0x10: Need authorization to write
0x20: Link should be encrypted for write

Do I need to move away from Tokio as I cannot split streams in TLS connections?

I use Tokio to create plain TCP sockets, call tokio::io::split() and the read/write halves get handed to separate threads. They use the async socket read/write APIs with await to accomplish the IO. Our data flow is fairly isolated in the in/out directions, so this model works well in our case. So far so good.
Now am looking at adding TLS support on top. Some of the TLS libraries don't allow splitting the stream for various reasons:
tokio-rustls (implemented with rustls) allows splitting, but it is relatively new
I would prefer to use tokio-openssl (implemented with openssl), which has been around for much longer, but openssl does not support it. This is probably because events like TLS renegotiation need to be propagated to the read/write halves (rustls manages it because it a native Rust implementation).
So the same thread needs to do the reads/writes. This implies that the socket needs to become non-blocking now: can't wait for data to come in, as data may need to be sent out immediately (and vice versa).
If I understand correctly, the Tokio/await paradigm doesn't make sense with the non-blocking sockets. Is my understanding correct?
Any other ideas in this scenario also welcome. I hope we don't need to abandon Tokio after all the effort put in so far.
It's true that async/await enabled TLS libraries such as tokio-tls require the provided stream to not have been split, however once you have wrapped your stream in a TLS layer, you can split that wrapped stream using tokio::io::split.
Using streams in this way correctly handles all details regarding blocking and non-blocking IO. You do not need to manually configure flags such as O_NONBLOCK, since Tokio's TcpStream and tokio-tls's TlsStream handle these details for you behind the scenes.
Using a library that provides blocking sockets would naturally not be compatible with Tokio. This is not new, and is for the same reasons that you can't use std::net::TcpStream within Tokio, as it is a blocking stream. Tokio provides alternate stream types for these purposes to avoid these issues.
If you wanted to use a non-async/await enabled ssl crate, you can perform the crypto on in-memory buffers, and manually write the encrypted data using Tokio's TcpStream. The async/await enabled ssl libraries all function in this way.

Simulating a BLE Pairing Mode on ESP32

I've been working on a device that includes an ESP32. I set up a secure GATT server similar to the Secure Gatt Server Example with a custom service with Man in the Middle (MITM) based encryption. Currently pairing setup is Just Works, and when a client connects to the device they are prompted to pair and thus are bonded with key exchange (although it looks like Justworks disables MITM when I did more investigation for this question).
We do not have any real IO except for one button on the device, but I would like to limit pairing to a certain window of time after the Pairing button is pressed, or to have a "pairing mode" that the device enters (I have worked on another device that may have more of a classic pairing mode that was easier to work with). I know that's not explicitly part of the IDF API, but I'm looking for some guidance on how to approach something like a "pairing mode."
Would setting the IO capability to ESP_IO_CAP_IO work for using a button for the Yes/No? I don't see anything relevant in the documentation about how to configure this. In fact the enum does not appear elsewhere in the IDF sourcecode, nor does the mentioned relevant file stack/btm_api.h help.
Is there a way to disable / enable pairing on command? Would it be some type of change to advertising?

suggestions for my monitoring system?

I'm a young professional who's into embedded design, IT networking, control/monitoring systems and much more. Currently, I'm developing a monitoring system using a device from Tibbo Techonology, their DS1102.
http://tibbo.com/products/controllers/ds110x/ds1102
It's a programmable device that covers serial and ethernet communications. For my project, its main tasks are serial data collection and database population. Serial communication is done through RS485 and database used is MySQL 5.5. My database is hosted on a public IP which also runs a webserver for the interface while my device is behind a NAT. It connects to the database directly using the public IP.
I'd like to ask for advices so that I can enhance and upgrade it. Right now these are the
questions I'd like to ask.
Which is better? Having the server on a public IP or using port forwarding?
I'm also using it as webserver for the interface of my monitoring system.
To communicate with the device (rebooting, changing IP etc), I wrote an application in
python using UDP (using port 65535 of device) and also set the device to communicate with the application for specific commands. My concern is I want to encrypt the communication between my python app and the device both ways. The only available function for both encrypting and decrypting on the DS1102 is RC4. What are your thoughts on using RC4 for this application? Also, I'm planning to do port forwarding on port 65535 so that I can use my python app from the outside. Can RC4 be reliable for this too? I really want to learn how to use encryptions properly.
I'm also planning to implement SMTP for alert messages. Tibbo has a sample code from which I based mine. Problem is, it's on AUTH PLAIN LOGIN. I think I want to turn it to STARTTLS later. Can you recommend some lessons on the algorithm of STARTTLS?
What are those details on MAIL FROM:<> and RCPT TO:<>? Because on using the command
DATA, the programmer can write anyway From: and To: which can make his identity someone else.
That's it for now. Suggestions are very welcome.
You can also share some good reading materials and links. I'm always hungry for learning. :)
Thanks for your time.
2.
Encryption substitutes the confidentiality of an arbitrary amount of data (the plaintext) with the confidentiality of a small amount data (the key). In other words, your communication is only as confidential as the key – if the shared secret key leaks out, the encryption is worthless. More on this.
Also note that plain RC4 provides no authenticity (message integrity). An adversary can modify messages as much as he wants. He can even send his own messages which will be considered perfectly valid by the cipher. Verifying the validity of the messages is is up to the code that parses the messages.
If your messages are simple (only a few bytes or so), an adversary could simply send random bytes until they decrypt such that they form a valid message, without knowing anything about the key. This happens on average after only 100 attempts for a 1-byte message for example.
You will obviously have to use some sort of a nonce to prevent trivial replay attacks.
RC4 is also rather quirky per se. I guess you are already aware of the numerous "drop-n" variants and so on.
In short, protocol design is perilous. Even experts often get it wrong (look at WEP for example). The most straightforward way to solve this would be to find hardware that can handle an existing protocol such as TLS.

Let two UDP-servers listen on the same port?

I have a client which sends data via UDP-broadcast. (To let's say 127.0.0.255:12345)
Now I want to have multiple servers listening to this data. To do so on a local machine, they need to share the port 12345 for listening.
My question is, if that is possible, if there are any disadvantages and if there could be problems with this approach.
There is one alternative which unfortunately brings with a lot of overhead:
Implement some kind of registration-process. On startup, each server tells the client its port. The client then sends the messages to each port (having to send the data multiple times, some kind of handshaking needs to be implemented...)
Do you know any better alternative?
If that matters:
I'm using C++ with Boost::Asio. The software should be portable (mainly Linux and Windows).
You will have to bind the socket in both processes with the SO_REUSEPORT option. If you don't specify this option in the first process, binding in the second will fail. Likewise, if you specify this option in the first but not the second, binding in the second will fail. This option effectively specifies both a request ("I want to bind to this port even if it's already bound by another process") and a permission ("other processes may bind to this port too").
See section 4.12 of this document for more information.
This answer is referenced to the answer of cdhowie, who linked a document which states that SO_REUSEPORT would have the effect I'm trying to achieve.
I've researched how and if this option is implemented and focused mainly on Boost::Asio and Linux.
Boost::Asio does only set this option if the OS is equal to BSD or MacOSX. The code for that is contained in the file boost/asio/detail/reactive_socket_service.hpp (Boost Version 1.40, in newer versions, the code has been moved into other files).
I've wondered why Asio does not define this option for platforms like Linux and Windows.
There are several references discussing that this is not implemented in Linux:
https://web.archive.org/web/20120315052906/http://kerneltrap.org/mailarchive/linux-netdev/2008/8/7/2851754
http://kerneltrap.org/mailarchive/linux-kernel/2010/6/23/4586155
There also is a patch which should add this functionality to the kernel:
https://web-beta.archive.org/web/20110807043058/http://kerneltrap.org/mailarchive/linux-netdev/2010/4/19/6274993
I don't know if this option is existing for Windows, but by defining portable as an attribute for software which runs on Linux too, this means, that SO_REUSEPORT is OS specific and there is no portable solution for my question.
In one of the discussions I've linked it is recommended for UDP to implement a master-listener which then provides the incoming data to multiple slave-listeners.
I will mark this answer as accepted (though feeling kind of bad by accepting my own answer), because it points out why the approach of using SO_REUSEPORT will fail when trying to use it with portable software.
Several sources explain that you should use SO_REUSEADDR on windows. But none mention that it is possible to receive UDP message with and without binding the socket.
The code below binds the socket to a local listen_endpoint, that is essential, because without that you can and will still receive your UDP messages, but by default your will have exclusive ownership of the port.
However if you set reuse_address(true) on the socket (or on the acceptor when using TCP), and bind the socket afterwards, it will enable multiple applications, or multiple instances of your own application to do it again, and everyone will receive all messages.
// Create the socket so that multiple may be bound to the same address.
boost::asio::ip::udp::endpoint listen_endpoint(
listen_address, multicast_port);
// == important part ==
socket_.open(listen_endpoint.protocol());
socket_.set_option(boost::asio::ip::udp::socket::reuse_address(true));
socket_.bind(listen_endpoint);
// == important part ==
boost::array<char, 2000> recvBuffer;
socket_.async_receive_from(boost::asio::buffer(recvBuffer), m_remote_endpoint,
boost::bind(&SocketReader::ReceiveUDPMessage, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)

Resources