-
Notifications
You must be signed in to change notification settings - Fork 2k
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
gcoap: add DTLS integration #12104
gcoap: add DTLS integration #12104
Conversation
Pinging people that I think might be interested in this @kb2ma @leandrolanzieri @smlng @tcschmidt @chrysn |
What's missing for this to not be WIP anymore? |
Thanks for working to move this forward, @benpicco. For my part I can only say it is high on my list to review after 2019.10 is released. |
@benpicco I guess you're right, it's not WIP anymore. It just waits for the review ... and we all understand why :-) |
Oh I don't know why - I thought I'd wait until this is not WIP anymore before beginning a review. |
@pokgak If this is not WIP anymore, please squash! |
Thanks for the interest!
Some checks as required by the RFC is still not done yet.
These needs to be move to another PR:
Other than that, I have an incomplete version of DTLS sock with WolfSSL (currently this PR is only using tinydtls with DTLS sock), , that I'm using to make sure that the changes I've done here is not specific to tinydtls. For example setting the RIOT/sys/net/application_layer/gcoap/gcoap.c Lines 118 to 123 in 8a2f70a
A function to wrap that will need to be added to the DTLS sock API. Added this to TODO in tracking issue.
I prefer #11943 gets merged first before review on this PR, so you could set the "waiting for PR" label for now. |
d328465
to
2723b8f
Compare
I updated this PR and it is now not a WIP anymore. Compiling will still fail because of dependencies on other PRs (#11943, #12529).
I skipped this check based on the response I got in obgm/libcoap#420 (comment).
This can be done in follow up PR for DTLS sock. I prefer not to change that PR anymore until it is merged. TLDR: this PR is ready for review and testing it as is is not possible but I tested it locally by pulling in the dependencies from #11943 and #12529. |
So this needs a rebase now 😃 |
#define GCOAP_PORT (5683) | ||
#endif | ||
#endif /* MODULE_SOCK_DTLS */ | ||
#endif /* GCOAP_PORT */ | ||
|
||
/** | ||
* @brief Size of the buffer used to build a CoAP request or response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expected to see a comment similar to what was in Makefile.dep
. The additional 128 bytes deserves some explanation so the user can change it if that is reasonable.
Payload size might be bigger when using DTLS with ECC, causing errors not present
when using plain CoAP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rephrased and added the comment in dfdbb86
#ifdef MODULE_SOCK_DTLS | ||
#include "net/credman.h" | ||
|
||
#define SOCK_DTLS_GCOAP_TAG (10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you choose 10 for this value? Why not 1 or 5?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be any unsigned
values. No reason specifically why 10 is chosen here.
#ifdef MODULE_SOCK_DTLS | ||
#include "net/credman.h" | ||
|
||
#define SOCK_DTLS_GCOAP_TAG (10) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More importantly, why define this value here? If it was defined in gcoap.c
or gcoap.h
, you would not need gcoap_set_credential_tag()
, right? Is there any value to defining it in the application? Would gcoap ever need more than one credential? Do we need a distinction between a gcoap server credential and a client credential?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following this line of thinking, why not move all of the code from this PR in gcoap_cli.c
into gcoap itself? gcoap provides CoAP as a service, so why should every application need to add this code? With this approach the application/user only needs to provide credentials.c
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More importantly, why define this value here? If it was defined in
gcoap.c
orgcoap.h
, you would not needgcoap_set_credential_tag()
, right? Is there any value to defining it in the application?
Yup, you're right. The credential tag is defined in the client to avoid reserving values for the tag used in gcoap. Other modules (e.g. LWM2M) might also hard-code the tag used for the DTLS sock and then there will be a need to track the available tag somewhere to avoid collisions.
Would gcoap ever need more than one credential?
Yes. gcoap might be talking to other secure coap clients/servers that use different credentials.
Do we need a distinction between a gcoap server credential and a client credential?
No.
Following this line of thinking, why not move all of the code from this PR in
gcoap_cli.c
into gcoap itself? gcoap provides CoAP as a service, so why should every application need to add this code? With this approach, the application/user only needs to providecredentials.c
.
The credentials are added in gcoap_cli.c
because we do not want to make any assumption or limit what the name of the variables used for the credentials should be.
In general, the design of coupling DTLS sock with credman is to avoid limiting what the name of the credentials should be or where it can be found. This is left to the user to define.
Functional testing is going OK. I'm updating the automated tests in riot-coap-pytest. It took some work to update my installation of libcoap and aiocoap for DTLS, as you can see in the Materials section of README.md. I think it will take another day or two to get through this testing. |
I'd like to be sure this PR supports use of more than one credential. So, suppose there are two credentials, C1 and C2, with tags 1 and 2 respectively. C1 is the credential the gcoap CLI uses to initialize gcoap. Let's assume SOCK_DTLS_GCOAP_TAG is 1. An endpoint A sends a GET request to the gcoap device using credential C1. gcoap's Now suppose I use the gcoap CLI to send a message to an endpoint B. However, endpoint B requires use of credential C2. The CLI uses gcoap_req_send() to send the message to B. However, Let's assume we find a way for gcoap to send the message to endpoint B with a different sock. Now gcoap also needs to listen for a response on this sock for credential C2 as well as listen on the sock for credential C1. I don't see how this is possible without something like the async mechanism we have been discussing. Without DTLS, gcoap acts as a messaging hub. All communication can pass through the single Am I missing something here? |
Yes, sending a message to endpoint B, which uses credential C2 will fail. The above part should answer your question. The following is an idea that I had in the earlier implementation of DTLS sock. One approach to support use of more than one credential is to use a different sock for each credential as you've described above. Another approach to support more than one credential is to modify how a DTLS sock gets its credentials from credman (the credential storage module). The reason why a DTLS sock only supports one credential is that each sock can only have a single credential tag. See RIOT/pkg/tinydtls/include/sock_dtls_types.h Lines 37 to 50 in cfeb2a3
My early implementation actually uses an array of /* current implementation */
struct sock_dtls {
...
credman_tag_t tag;
...
};
/* earlier implementation */
struct sock_dtls {
...
credman_tag_t tag[MAX_CREDMAN_TAG];
...
} With this approach, supporting more than one credential per sock can be done by adding a new tag to the array. When looking for which credential to use, the DTLS sock can go through the tag array and find a credential that matches. The problem with this approach is that going through the tag array each time can be costly if there are a lot of credential tags added to the sock. There is also the problem of how to know which credential tag to use to when a packet arrived. But this approach is just an idea that I had implemented half-way before giving up due to said (possible) problems and opted for a simple and limited current implementation (which proves to be problematic now) TLDR: The current DTLS sock implementation is limited to only one credential per sock due to the design choices of DTLS sock. |
Thanks for the explanation.
gcoap certainly would appreciate the ability to continue to use a single sock. The limitation of a single credential significantly affects the usefulness of gcoap. If you think it's reasonable to extend dtls_sock in this way in the near future, then I won't get too concerned over the present limitation, and we can move forward. Please add a warning to the DTLS section of the gcoap doc though.
If an application needs a lot of credential tags, they need the resources to deal with it. I would think that most applications would have limited requirements here.
It seems like there is a strong association between a remote endpoint / DTLS session and a credential. dtls_sock could use the remote to find the expected credential. |
* gcoap will automatically encrypt/decrypt CoAP packets with DTLS before | ||
* sending/receiving them over the network. | ||
* | ||
* To read more on DTLS support in RIOT, refer @ref net_dtls and @ref net_sock_dtls. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth specifically mentioning configuration parameters here. I got hung up for a while on the default value of 1 for tinydtls DTLS_PEER_MAX.
I have finished a first pass at functional testing and updating the riot-coap-pytest automated tests. You can see what works in the Setup section of the test There are 3 issues at present:
On (3) I was able to manually register with a DTLS based RD server using the gcoap CLI example in PSK mode, but the cord_ep example froze early in handshaking. |
Another issue, as first described in 12959: There is no mechanism in gcoap to close a session. I suppose this situation is manageable if gcoap only talks to at most DTLS_PEER_MAX (tinydtls) unique peers. On the other hand, there are scenarios that would like to return a 5.03 Service Unavailable if unable to open a new session. |
@pokgak, @cgundogan -- what's the status with this PR and #12959? Are you blocked or just otherwise busy? Is the best solution to work sock_async into gcoap and #12907 for sock_dtls? |
sorry @kb2ma, I'm a stuck with another project right now and won't have much time to work on this for now.
Main problem right now is that sock_dtls blocks while waiting for handshake messages. If we can avoid that with sock_async then it may be the solution. |
Gotcha. #13386 adds sock_async to gcoap and should be ready to experiment with when you get a chance. |
Just for the record: I played around with this PR a bit and had some problems using it together with various counterparts on the linux side (ie. libcoap, aiocoap, coap-shell). |
Glad to hear it!
If you can verify #12907 sock_async for tinydtls, I can try rebasing this work on that in @pokgak's absence. At least he should be available for questions. |
Yup, I'm currently also looking at #12907. |
There have been some major changes to gcoap and sock_dtls since this PR is opened. #12907 is working now too. I'm closing this PR and will open another one with the updated version. My plan is to first rework the credman workflow as per my discussion with @kb2ma and then use that with the new async sock_dtls. |
Any news on this? |
I'm not working on this at the moment. |
Should we take this over? |
Yes, go ahead. I think @leandrolanzieri looked into this already, so maybe you guys can sync up. |
#15549 did that |
Contribution description
This PR add DTLS support in gcoap.
Among the changes done in this PR are:
gcoap_set_credential_tag()
to tell credman which credential to use. For other application that is similar to gcoap where the user does not have direct access to the sock used, this is how DTLS integration using DTLS sock API can be done.Section 9.1 of the CoAP RFC mentions checks that must be done for CoAP implementations that integrates DTLS. I have not done any of said checks in this PR yet.
Testing procedure
NOTE: This PR will currently fail compile due to dependencies on other PR. For testing, you will need to manually pull in changes from #11943 and #12529.
Testing have been done between two
samr21-xpro
and also between anucleo-l476rg
and a RPI with 802.15.4 radio. On the RPI, I've tested this PR with the following stack on the Pi:coap-server
andcoap-client
aiocoap-client
For testing between two RIOT nodes, simply flash
example/gcoap
onto the boards and send a CoAP get from the client to the server using:When testing with a Pi, I encountered some problem when using link-local IPv6 so it is better to use the global address. For that some changes are needed to the Makefile:
Then setup RADVD on the Pi and you can proceed with the instructions above.
Issues/PRs references
DTLS sock tracking issue: #10897