Skip to content
This repository has been archived by the owner on Sep 6, 2023. It is now read-only.

Using DTLS, with UDP, and generalized packet objects #188

Open
MrSurly opened this issue Sep 28, 2017 · 8 comments
Open

Using DTLS, with UDP, and generalized packet objects #188

MrSurly opened this issue Sep 28, 2017 · 8 comments

Comments

@MrSurly
Copy link
Contributor

MrSurly commented Sep 28, 2017

End Goal

Using DTLS for LoRa data. Why? Because I'm using the RFM95 (sx1276) module that doesn't appear to have encryption, and the RFM69 (sx1231)modules (that do have encryption) are using AES ECB, which is bad for the highly repetitive nature of my packets.

Intermediate Goal

Enable DTLS for ordinary UDP sockets, using mbedtls, which is already used in ussl.

Doing this for UDP sockets seems relatively straight-forward, as all µPy sockets implement an underlying "stream" protocol, thus the ussl module will work, with some modification.

It would be nice if there were a generic µPy "stream" protocol class that could be subclassed (to talk to LoRa, which is very UDP-like), and handed directly to (modified for DTLS) ussl for wrapping -- or is there already?

@dpgeorge
Copy link
Member

dpgeorge commented Oct 5, 2017

It would be nice if there were a generic µPy "stream" protocol class that could be subclassed

Do you mean on the C or Python side? On the C side you just make an mp_stream_p_t struct for your type. But I guess you are asking about how to do that on the Python side. In that case you may want to look at micropython/micropython#3034 which adds an io.IOBase class for this purpose.

@MrSurly
Copy link
Contributor Author

MrSurly commented Oct 5, 2017

But I guess you are asking about how to do that on the Python side. In that case you may want to look at micropython/micropython#3034 which adds an io.IOBase class for this purpose.

Yes, this is exactly what I had in mind. Since ussl expects something stream-like, and calls mp_get_stream_raise(), it requires the underlying class to implement mp_stream_p_t. I just want something that implements mp_stream_p_t, but allows me to overload read, write, and ioctl (in Python), allowing me to pass an object to ussl that actually implements datagrams over LoRa.

@dpgeorge
Copy link
Member

dpgeorge commented Oct 5, 2017

Ok. That IOBase class allows you to implement read/write on the Python side, but not ioctl (but not hard to add the latter).

@MrSurly
Copy link
Contributor Author

MrSurly commented Oct 5, 2017

Also, I should mention, I have DTLS working for plain-vanilla UDP sockets, with the exception that hello verify cookies aren't working for me.

Implementation is somewhat involved -- there are a lot of things that have to be just right. But that's the nature of socket programming.

C code changes:

  • Adding an ioctl call to the usocket to allow ussl to determine if the socket is an SOCK_STREAM or SOCK_DGRAM. ussl needs this to properly set up the mbedtls functionality.
  • Implementing socket.accept() for SOCK_DGRAM sockets. Let me explain. This works by calling recvfrom on the listening socket with MSG_PEEK to get the address, then connect-ing the listening socket to the remote host, and returning the listening socket as the connected client socket. This means the returned socket still has that first UDP message queued up for ussl This also allows read and write calls from ussl to work properly, because the UDP socket is connect-ed. socket.accept() then modifies the listening socket, and re-binds it to the original listening IP/port with SO_REUSEADDR ioctl set. Incidentally, the first bind of the listening socket also has to have this set, so I'm considering hard-coding that into socket.bind().

Python code requirements:

  • UDP sockets passed to ussl.wrap_socket must be the result of socket.accept() for the reasons listed above. Additionally, they must be made non-blocking before being passed, because that's a requirement for DTLS to work. I might just have accept set returned UDP client sockets as already non-blocking.

@MrSurly
Copy link
Contributor Author

MrSurly commented Oct 5, 2017

Ok. That IOBase class allows you to implement read/write on the Python side, but not ioctl (but not hard to add the latter).

Yeah, that's something I was considering implementing (though I'd have to ask you how to do it!), for this use-case.

And, yes, I'd need ioctl.

Is that going to be merged?

It's worth noting that this is only to support my end goal of robust encryption over LoRa. I'm not even sure if it will work properly given the max LoRa payload size, and other factors (such as filtering on client MAC, etc). But I figure if it can be made to work for UDP (as intended), then there's a good shot at using that as a stepping stone to other transports.

@nickzoic
Copy link
Collaborator

nickzoic commented Oct 7, 2017

Hmmm, this is also interesting to me as I'm looking at ESP-Now which passes small messages around in an ad-hoc manner (see #176)

It has a send method and a recv callback and I'd like to expose that as a generic datagram transport.

@MrSurly
Copy link
Contributor Author

MrSurly commented Oct 16, 2017

I haven't abandoned this. I'm juggling several work projects right now. This is required for one of them, and I'll revisit when I'm working again on that project.

@malachib
Copy link

Curious if you made any progress. I'm doing some similar work on the ESP8266 mbedtls DTLS and hitting handshake problems

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants