Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement security protocols #2

Open
robertmuth opened this issue Aug 19, 2018 · 18 comments
Open

implement security protocols #2

robertmuth opened this issue Aug 19, 2018 · 18 comments

Comments

@robertmuth
Copy link
Owner

No description provided.

@KM4YRI
Copy link
Contributor

KM4YRI commented Aug 23, 2018

+1, as even open-zwave hasn't yet implemented S2 security. The OZW developers don't really seem to care either, they just closed an open ticket asking for it, saying why bother when there aren't any S2 devices out there (obviously there are now but still they don't care).

I started looking into what it would take to add S2 security to OZW in a fork, but my C++ skills probably aren't up to the task. I could probably get it done in Python and would volunteer to do that in PyZwaver, if the author doesn't have time to do it. The offer is open though. Not sure what that timetable would be but hopefully the author of this project is more open to it than the authors of openzwave.

@robertmuth
Copy link
Owner Author

robertmuth commented Aug 24, 2018

My plan is to add S2 support but no support for S0.
Implementing security will cause quite a bit of churn in the internals of the library.

I have an S2 capable device to play with and hope to get the initial key exchange
done this weekend. Since there is no reference implementation, this will be kind
of hard and every help is appreciated.
I'll post updates and requests for help to this issue.

@KM4YRI
Copy link
Contributor

KM4YRI commented Aug 24, 2018

I'd be happy to assist in testing if needed. I'm just starting out with Z-wave, at the moment I'm actually doing some web scraping of the z-wave alliance site of all the devices to get a more accurate idea of the differences between various devices based on supported classes and their supported versions of them. I'm pretty disappointed that openzwave doesn't support S2 so I'm willing to invest some time to get an implementation going, even if it's just on the support side, helping out where needed. From what I understand, the USB z-wave devices are pretty much just a pipe and all the encryption and security protocols must be handled by the top-level application. I'm assuming that as long as they've got a specification for it that it's enough to make a Python implementation from scratch.

Good luck and feel free to reach out if there's anything I can help with.

@robertmuth
Copy link
Owner Author

Implementation work has begun.

This feature will drag in a fairly heavy dependency on "cryptography"
(https://cryptography.io/en/latest/)

By default the corresponding import is still disabled.
Set SECURE_MODE to True in node.py to enable it.

Development/debugging is currently done using a real device an iterating via

./example_tool.py --verbosity=20 --serial_port=/dev/ttyUSB0 unpair
./example_tool.py --verbosity=30 --serial_port=/dev/ttyUSB0 secure_pair

@robertmuth
Copy link
Owner Author

Some progress towards the handling the initial key exchange.
A bunch of security primitives related to Security2 are now in security.py

Biggest omissions are around Nonce generation for SPAN.
(cf.: http://zwavepublic.com/sites/default/files/command_class_specs_2017A/SDS13783-5%20Z-Wave%20Transport-Encapsulation%20Command%20Class%20Specification.pdf )

The other missing part is unit tests confirming that these primitives actually work as intended.
Without those unit tests it will be a long chain of trial and error before the first
MessageEncapsulation can be decrypted.

Any help is greatly appreciated

@robertmuth
Copy link
Owner Author

Most of the crypto primitives are now in place but have not been fully debugged.
The next milestone is to get the unit-test "TestKex" pass.
(make test_security)
If anybody has spare cycles feel free to send me a pull request.

@KM4YRI
Copy link
Contributor

KM4YRI commented Sep 12, 2018

Question for you, apologies if it's slightly off-topic for this issue.

This USB stick advertizes full S2 security: https://www.thesmartesthouse.com/products/zooz-usb-z-wave-plus-s2-stick-zst10

However my understanding of all common Z-Wave USB sticks was that the serial protocol left all of the S2 security to the end-user application to implement (hence this issue being open). But this product says that S2 is implemented out of the box, and is otherwise transparent.

How can that be? And would it be compatible with PyZwaver and/or OpenZwave?

@robertmuth
Copy link
Owner Author

My understanding is that s2 is largely done in software at the application layer.
In fact, part of the development I did so far was done with an ancient series 300
usb stick from aeotec. There probably are some advanced features that require a
zwave plus (series 500) device but I have not reached that point.

BTW: I wont have much time to work on this till the of the quarter so feel free
to give it a try.

@aromanro
Copy link

Did you manage to decrypt the first S2 encrypted packet (the 'echo')? I'm implementing the same thing for some closed source project and I'm having troubles with it... ECDH, PRNG and decryption are good as far as I can tell, but there is some mistake in there... it would be nice if they would provide some test vectors for nonce generation, for example...

@robertmuth
Copy link
Owner Author

sorry, no progress here. I think the best thing would be to reach out to the z-wave alliances and ask
for an example communication transcripts including all the internal state on both sides.

@aromanro
Copy link

In the meantime, I managed to decrypt it. It's quite cumbersome to implement it, one needs to patiently check each referred RFC for test vectors and check against those. Apparently it's doable, but it takes patience and time.

@aromanro
Copy link

By the way, I've seen this: "My plan is to add S2 support but no support for S0." FYI, S0 is much simpler than S2 to implement, plus you have open source projects that already implement it, so if you get stuck you can look into those to see what they do. There is no open source implementation of S2 as far as I can tell and it's much harder to implement. Besides the S2 class one has to implement for example the transport class which is quite a bit of work by itself.

@robertmuth
Copy link
Owner Author

@aromanro if you can post a transcript of the message exchanged of the initial key exchange including
the internal crypto state of both sides - that would be tremendously helpful.

Re S0 support, I actually got that to work in a predecessor of this library but I do not think it is worth it. There are too many message that need to be exchanged leading to poor latency/reliability.

@aromanro
Copy link

S0 is working nicely in the software I implemented. Indeed there is the overhead of requesting the nonce and getting it each time, but it's not that bad. The reliability does not seem worse than without S0, if implemented right. You can even send an encrypted packet specifying with it that you need another nonce for the next packet, which cuts from overhead a little.

As for that log, I'm not sure I should provide it, since I'm working on a closed source project.
My advice would be to check each step from the documentation with patience, and test against the test vectors provided in referred RFCs. That's how I figured it out.

@robertmuth
Copy link
Owner Author

Can you point me at the rfc with the test vectors.

@aromanro
Copy link

There are various RFCs, pointed out in the documentation. The starting point for S2 implementation is 'Z-Wave-Transport-Encapsulation-Command-Class-Specification' pdf. For DiffieHellman I did what is said in this page http://cr.yp.to/ecdh.html and used gcrypt. For CBC-MAC I used this https://tools.ietf.org/html/rfc3610 for the test vectors at the end and the description which appears to me not so clear, I had a little bit of fighting with it until I managed to decrypt and authenticate. For AES CMAC I used gcrypt, I implemented my own PRNG according to the specs from here: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf Basically I combined using gcrypt, my code and some black magic :) in order to have it working. It's quite a bit of work involved...

@robertmuth
Copy link
Owner Author

So I got reasonably far with this in this test:
https://github.com/robertmuth/PyZwaver/blob/master/Tests/security_test.py

using a standard python crypt library. I am going to clean it up a little over xmas.
Would you be willing to have a look at it and let me know where there first deviation
happens compared to your implementation and what the expect value at that point would be?

@aromanro
Copy link

aromanro commented Dec 14, 2018

Not really, I'm very sick of my own code about this :(

Checking my own code to find where the problems were was nightmare enough, trying to figure that out in some other code is more than I can stand right now, sorry.

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

No branches or pull requests

3 participants