aiocoap icon indicating copy to clipboard operation
aiocoap copied to clipboard

Guide about using EDHOC in the client ?

Open MohammedAbderrahmane opened this issue 10 months ago • 3 comments

Hello all,

I am currently working on a project involving IoT security, and I want to include the EDHOC key exchange. I tried looking at the examples, source code, and the EDHOC guide in the documentation, but I haven't had any success so far.

Is there any guide on using EDHOC in the client to establish the OSCORE context?

MohammedAbderrahmane avatar Mar 03 '25 13:03 MohammedAbderrahmane

Where are you exactly stuck? You've mentioned the EDHOC guide already, but granted, that mainly talks from the perspective of the tools and not the libraries.

It's not replacing the docs, but there is an example that shows what happens in the client application. You can either load a file the same way, or just put a dictionary with the file's content right into the application setup:

https://github.com/chrysn/aiocoap/blob/22f8eaaa790cb7404d942a3a44ab1f0c24c9b9d4/src/aiocoap/cli/client.py#L184-L188

I do plan updating the guide (as well as enhancing that file format), but does this suffice to get you unstuck? (Happy to help if not; either way, let's keep the issue open to ensure that this will eventually be addressed in the guide.)

chrysn avatar Mar 03 '25 15:03 chrysn

Hello .thank your for the response.

I used the the EDHOC guide . However, the EDHOC exchange isn’t recorded in Wireshark. The only recorded packets are the CoAP GET request and the ACK response.

Then, I made this code which is similar to the guide, but the same issue persists.

The client code:

  context = await aiocoap.Context.create_client_context()
    credentials_path = Path("client.cred.diag")

    context.client_credentials.load_from_dict(
        cbor2.loads(cbor_diag.diag2cbor(credentials_path.open().read()))
    )

    request = aiocoap.Message(
        code=aiocoap.Code.GET
    )
    request.set_request_uri("coap://192.168.1.100/")

    requester = context.request(request)

    response_data = await requester.response

    response_uri = response_data.get_request_uri()
    print(
            f"Response arrived from {response_uri}",
        )

while the server code:

credentials_path = pathlib.Path("server.cred.diag")

    import cbor_diag
    import cbor2

    credentials = CredentialsMap()
    credentials.load_from_dict(
        cbor2.loads(cbor_diag.diag2cbor(credentials_path.open().read()))
    )

    root = Res.Site()
    root_secured = OscoreSiteWrapper(root, credentials)

    root.add_resource([], Welcome()) # return back "hello from server"

    coap_context = await aiocoap.Context.create_server_context(
        root_secured, bind=('0.0.0.0', 5683)
    )
   await asyncio.get_running_loop().create_future()

The same issue occurs here: the request is sent, and the response is received, but there is no EDHOC key exchange, which means no OSCORE secured communication.

I think the client should use aiocoap.edhoc.EdhocCredentials.establish_context(). but i couldnt find any examples and i couldn’t figure out how to use it.

MohammedAbderrahmane avatar Mar 05 '25 18:03 MohammedAbderrahmane

Could you verify that all required modules are installed (python3 -m aiocoap.cli.defaults)?

Apart from finding out what went wrong here, the main takeaway is that the pending credentials system overhaul needs to be fed into the request process even when the modules are not present: It's bad enough that misconfigured credentials would turn a presumably secure request into an insecure one, but worse that even with correct configuration, aiocoap may not pick up the hints.

chrysn avatar Sep 24 '25 08:09 chrysn