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

Initial implementation of IEEE 802.15.4 security #15150

Merged
merged 6 commits into from
Dec 9, 2020

Conversation

fabian18
Copy link
Contributor

@fabian18 fabian18 commented Oct 3, 2020

Contribution description

This PR aims to integrate initial IEEE 802.15.4 security support for RIOT.
The implementation waives to use a proper key store to mitigate complexity. Instead it always uses the key that has been set via
NETOPT_ENCRYPTION_KEY. So in terms of specification, the key is always implicitly known (IEEE802154_SCF_KEYMODE_IMPLICIT).
This is what I have been using as a reference.

Testing procedure

You can test the implementation with examples/gnrc_networking, if you add USEMODULE += ieee802154_security and try ping6. It is supposed to work with any 802.15.4 radio. If you have an at86rf2xx with SPI, you can additionally add USEMODULE += at86rf2xx_aes_spi, if you want to utilize the transceiver´s hardware crypto module.
I tested the implementation on two nucleo-f767zi with an at86rf233.

Issues/PRs references

Could be related to #14950

@benpicco benpicco added Area: network Area: Networking Area: security Area: Security-related libraries and subsystems Type: new feature The issue requests / The PR implemements a new feature for RIOT labels Oct 3, 2020
@benpicco
Copy link
Contributor

benpicco commented Oct 3, 2020

Awesome, thank you!
Want to split out 5c2a1eb as a separate PR?
While technically an API change, we should be able to merge that quick.

I'll look into the other things soon.

@jia200x
Copy link
Member

jia200x commented Oct 5, 2020

I think code-wise makes a lot of sense. My only concern is the dependency from sys/ieee802154 to netdev, specially since we are currently migrating to the Radio HAL.
But I think integrating it to netdev would work for applications that still rely on that.

Also, do you think it could make sense to (optionally) expand the radio_ops of the Radio HAL to expose the primitives to use the internal crypto accelerator?
I think in the long run would be nice to have a separated crypto structure, but in the short run we could live with this in the radio descriptor.

what do you think?

@fabian18 fabian18 mentioned this pull request Oct 5, 2020
@fabian18
Copy link
Contributor Author

fabian18 commented Oct 5, 2020

Want to split out 5c2a1eb as a separate PR?

Did this real quick

@fabian18
Copy link
Contributor Author

fabian18 commented Oct 5, 2020

Also, do you think it could make sense to (optionally) expand the radio_ops of the Radio HAL to expose the primitives to use the internal crypto accelerator?

That´s the hard question. I could try to add these and see what comes out. Or do you want to add the CAP´s ?

@jia200x
Copy link
Member

jia200x commented Oct 5, 2020

I could try to add these and see what comes out.

That could be nice!

@jia200x
Copy link
Member

jia200x commented Oct 5, 2020

btw, I think this could work already out of the box using netdev_ieee802154_submac! Since it depends on netdev_ieee802154.

That means, CC2420 and nrf802154 can be used with full CSMA-CA and retransmissions + security

@benpicco
Copy link
Contributor

benpicco commented Oct 5, 2020

Also, do you think it could make sense to (optionally) expand the radio_ops of the Radio HAL to expose the primitives to use the internal crypto accelerator?

That´s the hard question. I could try to add these and see what comes out. Or do you want to add the CAP´s ?

I mean ideally we would have a general crypto API that is either backed by a hardware or a software implementation depending on the platform. But that is for another endeavor.

I like your idea that the radio driver can 'catch' those netops, so if the radio can handle crypto itself we already get this abstraction for free.

@fabian18
Copy link
Contributor Author

fabian18 commented Oct 5, 2020

btw, I think this could work already out of the box using netdev_ieee802154_submac! Since it depends on netdev_ieee802154.

So as a first step, I should move my ieee802154_sec_context_t from netdev_ieee802154_t to netdev_ieee802154_submac_t?

@jia200x
Copy link
Member

jia200x commented Oct 5, 2020

So as a first step, I should move my ieee802154_sec_context_t from netdev_ieee802154_t to netdev_ieee802154_submac_t?

It shouldn't be necessary, since netdev_ieee802154_submac_t already depends on netdev_ieee802154_t and most IEEE 802.15.4 drivers depends on netdev_ieee802154_t (but not netdev_ieee802154_submac_t). At the moment we remove netdev from the IEEE 802.15.4 drivers we can decide where to allocate that context (I would say the SubMAC is an option)

@maribu maribu self-requested a review October 6, 2020 08:20
@benpicco
Copy link
Contributor

Sorry for the long radio silence, I tried to do some interoperability testing, but wasn't very successful on that end.

  • for Linux I followed this guide using the nl802154_llsec branch of wpan-tools and made sure to enable the IEEE802154_NL802154_EXPERIMENTAL option in the kernel config. I would however only get a netlink: 'iwpan': attribute type 1 has an invalid length. when trying to configure the encryption key 😞

  • for Zephyr I flashed samples/net/sockets/echo_server with the NET_L2_IEEE802154_SECURITY option enabled onto a nrf52840dk_nrf52840. I also set CONFIG_NET_L2_IEEE802154_SECURITY_CRYPTO_DEV_NAME to CRYPTO_TC and enabled TinyCrypt since the driver for the nRF build-in crypto hardware was not supporting asyc operations which apparently the MAC layer needs.
    With that I got no run-time errors, but still no encrypted traffic 😕

Anyway so with a samr21-xpro this is sending encrypted packets just fine.
I tried on an openmote-b with netdev_ieee802154_submac and cc2538_rf but that would not get me any encrypted traffic. It wouldn't decode the packets from samr21-xpro either.

avr-rss2 also has an at862xx radio, but the memory mapped variant that's not supported by the aes_spi driver just yet - it would still encrypt and decrypt packets.

The at86rf233 radio attached to an esp32 also worked fine with encryption.

I also noticed nodes can still receive unencrypted frames - that'll be convenient if we want to do some Diffie-Hellman key exchange and have per-node keys 😀

Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash & rebase before addressing the review comments.

sys/net/link_layer/ieee802154/security.c Outdated Show resolved Hide resolved
sys/net/link_layer/ieee802154/security.c Outdated Show resolved Hide resolved
Copy link
Contributor

@benpicco benpicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A so this is only hooked up to the at86rf2xx driver so far, but it could be hooked up the the sub-MAC and then catch all drivers that implement the radio HAL? (That would be for a later PR)

I'm happy with starting at a basic but solid foundation so we can get results, and make it more practical going forward, so a hard-coded key for all nodes and just supporting a single driver is fine.

But those encrypt and decrypt routines are a bit scary - manipulating buffers with long lists of offsets… if there is a bug in there I wouldn't want to search it.
Those mathematical variable names need explanations, otherwise they are just cryptic.

sys/include/net/ieee802154_security.h Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/net/link_layer/ieee802154/security.c Outdated Show resolved Hide resolved
sys/net/link_layer/ieee802154/security.c Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Show resolved Hide resolved
sys/net/link_layer/ieee802154/security.c Show resolved Hide resolved
sys/net/link_layer/ieee802154/security.c Outdated Show resolved Hide resolved
sys/net/link_layer/ieee802154/security.c Outdated Show resolved Hide resolved
Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I again forget to submit my review, here is at least the chunk I looked at so far.

drivers/at86rf2xx/at86rf2xx.c Outdated Show resolved Hide resolved
drivers/netdev/ieee802154.c Outdated Show resolved Hide resolved
drivers/netdev/ieee802154.c Outdated Show resolved Hide resolved
sys/Makefile.dep Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
sys/include/net/ieee802154_security.h Outdated Show resolved Hide resolved
@benpicco
Copy link
Contributor

benpicco commented Dec 3, 2020

tests/ieee802154_security will need a Makefile.ci

@benpicco
Copy link
Contributor

benpicco commented Dec 6, 2020

@miri64 have your comments been addressed?

Comment on lines +425 to +426
uint32_t frame_counter = byteorder_ntohl(
byteorder_ltobl((le_uint32_t){aux->fc}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uint32_t frame_counter = byteorder_ntohl(
byteorder_ltobl((le_uint32_t){aux->fc}));
uint32_t frame_counter = byteorder_ltohl((le_uint32_t){aux->fc});

should also work now.

ahr->scf = _scf(ctx->security_level, ctx->key_id_mode);
/* If you look in the specification: Annex C,
integers values are in little endian */
ahr->fc = byteorder_btoll(byteorder_htonl(ctx->frame_counter)).u32;
Copy link
Contributor

@benpicco benpicco Dec 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ahr->fc = byteorder_btoll(byteorder_htonl(ctx->frame_counter)).u32;
ahr->fc = byteorder_htoll(ctx->frame_counter).u32;

feel free to squash directly

@miri64 miri64 dismissed their stale review December 8, 2020 19:14

My comments were addressed

@benpicco benpicco added Area: CI Area: Continuous Integration of RIOT components and removed Area: CI Area: Continuous Integration of RIOT components labels Dec 9, 2020
@benpicco benpicco dismissed their stale review December 9, 2020 12:57

re-ACK to re-trigger CI

@benpicco benpicco merged commit 1477a34 into RIOT-OS:master Dec 9, 2020
@maribu
Copy link
Member

maribu commented Dec 9, 2020

🎉 Good to have this in :-)

@fabian18
Copy link
Contributor Author

fabian18 commented Dec 9, 2020

Hurray 🎊. Thank you @benpicco and @miri64

@benpicco benpicco requested a review from jue89 December 9, 2020 22:49
@jia200x
Copy link
Member

jia200x commented Dec 10, 2020

congratz! One stop closer to the full MAC layer :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: network Area: Networking Area: security Area: Security-related libraries and subsystems CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Reviewed: 3-testing The PR was tested according to the maintainer guidelines Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants