Skip to content

feat: enable oscore credentials lookup and storage#1911

Open
BitFis wants to merge 3 commits intoobgm:developfrom
BitFis:feat/enable-external-oscore-credentials
Open

feat: enable oscore credentials lookup and storage#1911
BitFis wants to merge 3 commits intoobgm:developfrom
BitFis:feat/enable-external-oscore-credentials

Conversation

@BitFis
Copy link
Copy Markdown

@BitFis BitFis commented Mar 10, 2026

Work related to #1892

Enabling:

  • ensure oscore ctx is cleaned up
  • allow storage and provide oscore credentials
  • write example to load oscore credentials from file system
  • add API functions to override find and store echo and PIV / window values for storage

TODO:

  • Cleanup commit history
  • Remove older code
  • Cleanup internal reference counter
  • Check documentation and function names
  • Expand man page

@BitFis BitFis changed the title feat: enable oscore credentials lookup and storage Draft: feat: enable oscore credentials lookup and storage Mar 10, 2026
@mrdeep1
Copy link
Copy Markdown
Collaborator

mrdeep1 commented Mar 10, 2026

It is worth installing and running pre-commit to tidy up the source formatting.

@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 5 times, most recently from fdc8821 to 42c2033 Compare March 10, 2026 16:05
@mrdeep1
Copy link
Copy Markdown
Collaborator

mrdeep1 commented Mar 10, 2026

I suggest that you go through all the failed tasks and fix the associated issue before doing the next push. There is some overlap, but a lot of discrete issues that need to get fixed.

@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 3 times, most recently from 3b6f3cd to bd0d278 Compare March 10, 2026 17:31
@BitFis
Copy link
Copy Markdown
Author

BitFis commented Mar 10, 2026

I suggest that you go through all the failed tasks and fix the associated issue before doing the next push. There is some overlap, but a lot of discrete issues that need to get fixed.

Apologies for the spam, I am used to that all runs are canceled automatically if a new push has triggered it.

@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch from bd0d278 to 23a3852 Compare March 10, 2026 17:54
@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 4 times, most recently from 57a1bb3 to d2cd11c Compare March 19, 2026 20:56
@BitFis
Copy link
Copy Markdown
Author

BitFis commented Mar 19, 2026

@mrdeep1 please have another look. I will finalize it next week, but please check if this follows the appropriate format.
I followed up now the coap_oscore*_conf_t format. Which means, the find function returns the config object, which then internally is converted to the oscore ctx. This removes the need to provide access to the underlying oscore ctx, enabling for internal optimisations. But to enable that echo challange and PIV + window work as expected, I had to add some additional handlers. Also I added a lifetime tracker recipiant->ref to ensure that the oscore temporary credentials can be safely cleaned up, it seems something like it is required, since the recipient currently could be removed and may lead to unexpected behavior if still referenced.

For now maybe focus on the API expansions in coap_oscore and the general flow. I will cleanup some internals next week, so it should then be ready for final scrutiny should this approach be fine.

@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 11 times, most recently from c70a91d to e094227 Compare March 26, 2026 22:41
@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 8 times, most recently from 239d6e7 to 77f794b Compare March 30, 2026 14:49
@BitFis
Copy link
Copy Markdown
Author

BitFis commented Mar 30, 2026

Thanks for the short review.

I am seeing a lot of errors compared to the develop branch as per oscore_issues.txt.

Double checked the issue. The compile error I am not able to reproduce using gcc-11 and gcc-15 (latest).
Thought it should be resolved by not using sprintf but snprintf. Please verify on your side

The context not found issue is related to the extension with the coap_oscore_rcp_conf_t. I was not aware that multiple rcp can be provided inside the file format. I added a regression test with your content to ensure the parsing works as expected. Please add a comment if there are other special cases to take into account. As I understood all other values can not have multiple values.

Also in general I added a lot more tests, to ensure the quality stays. It comes sadly with a bit of complexity, but general following 3 features are provided:

  1. added new coap_oscore_rcp_conf_t and coap_oscore_snd_conf_t into the coap_oscore_conf_t (that was the source of your found bug) - enable expanding the conf via setters
  2. added the find function - this should be non intrusive and only change the find behavior if it is set. order of priority currently is:
    1. find function call -- potentially override internal stored oscore_ctx_t
    2. find oscore_ctx_t via the already implemented function -- no changes there
  3. The ref counter for the oscore_recipient_ctx_t, this also resolve the potential issue, if the recipient is deleted via coap_delete_oscore_recipient even thought its still referenced internally.

I also verified the that the code is following as close to the already used standard, including updating the function handler definitions. So hope this is now following the libcoap coding styling closely.

@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 2 times, most recently from 44ed81f to 636686f Compare March 30, 2026 15:17
@mrdeep1
Copy link
Copy Markdown
Collaborator

mrdeep1 commented Mar 30, 2026

Thanks. I will re-run compatibility tests which takes a bit of time and see what gets reported.

The compile error I am not able to reproduce using gcc-11 and gcc-15 (latest).

I'm using gcc-13 on ubuntu24 and -fsanitize=address,undefined. The update code builds fine this time. It looked like the check was doing a sizeof(p) to see whether it was safe to overwrite - a 64bit hex value was too much for the pointer size which was 8 bytes.

The recipient context will need to be extended to support group mode or pairwise mode and public key at a minimum, along with silent server.

@BitFis
Copy link
Copy Markdown
Author

BitFis commented Mar 31, 2026

Thanks. I will re-run compatibility tests which takes a bit of time and see what gets reported.

Brilliant, thanks for verifying

The recipient context will need to be extended to support group mode or pairwise mode and public key at a minimum, along with silent server.

With the provided implementation, the extension should be relative easy, so I don't see an issue for those extensions I would say 👍

@mrdeep1
Copy link
Copy Markdown
Collaborator

mrdeep1 commented Mar 31, 2026

The compatibility tests ran fine overnight.

I will start on reviewing the code later today / tomorrow.

Copy link
Copy Markdown
Collaborator

@mrdeep1 mrdeep1 left a comment

Choose a reason for hiding this comment

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

In general looking OK.

2 commits need to be merged into 1.

* _<contextid_hex>_<kid_hex>.txt_ for the OSCORE credential text in the
same format as for the *-E* option.
* _<contextid_hex>_<kid_hex>_seq.txt_ for persisted recipient sequence state
(sequence counter and replay window), stored as two uint64_t values.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Represented as hex values? How are the 2 values separated?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The _, i was hoping it formats as markdown, I replaced the wrapping _ now with `

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The back-ticks are dropped when building the man pages as in

       The dynamic credential files use the following naming format:

       •   <contextid_hex>_<kid_hex>.txt for the OSCORE credential text in the same format as for the
           -E option.

so, no need for them.

coap_oscore_rcp_conf_t *
coap_oscore_conf_add_rcp(coap_oscore_conf_t *conf,
const coap_bin_const_t *recipient_id) {
return coap_oscore_conf_add_rcp_internal(conf, recipient_id);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

coap_oscore_conf_add_rcp_internal() is not global_lock protected, and needs to be as it is scanning chains.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Function return should be prefixed with COAP_API.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm beginning to think that coap_oscore_conf_add_rcp_internal() should really now be renamed coap_oscore_conf_add_rcp_lck().

Copy link
Copy Markdown
Author

@BitFis BitFis Apr 6, 2026

Choose a reason for hiding this comment

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

Agree, given we will require the lock around those functions. Added comment to other conversation - #1911 (comment)

if (conf->sender_id.sender_id) {
coap_delete_bin_const(conf->sender_id.sender_id);
}
conf->sender_id.sender_id = new_sender_id;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unlikely that multiple threads are doing this concurrently, but this is not thread safe.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

There are now multiple returns from coap_oscore_conf_set_snd() which leave the global lock locked.

I suggest that you rename coap_oscore_conf_set_snd() to coap_oscore_conf_set_snd_lkd() and create a wrapper like coap_oscore_conf_add_rcp() and remove coap_lock* from within coap_oscore_conf_set_snd_lkd().

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I am not sure that this function can be used at all safely within the find function callback. Are you sure a lock is required. Since for me it seems the conf pointer is created and passed into libcoap. So never shared between libcoap and the application. Maybe adding a information that the function is not thread safe, but the conf should never really be accessed by multiple threads. Thougth not sure, if you have some plans into another direction.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A part of me questions whether we need this function at all, unless we build the entire configuration without using a configuration file.

As we are just building a configuration file from a single thread, then we can get away with no locking. However, it should not be called twice and so replacing a now stale copy of sender_id is unexpected. But someone will try to do that.. If it is updated from find function, that could be executing in any thread.

I also think you have got away with sender_id still working with the configuration file with

CONFIG_ENTRY(sender_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),

and so sender_id.sender_id just happens to work when updating the top level sender_id.

Copy link
Copy Markdown
Author

@BitFis BitFis Apr 6, 2026

Choose a reason for hiding this comment

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

that is correct, generally I see a benefit of being able to build the configuration without the configuration file. I believe this is an important optimization in the future, to then also potentially enable passing the memory from application space to optimize on ram usage.
For the example case in the server, it shows well, to achieve the same functionality, the file memory would need to be manipulated before passing to the coap_new_oscore_conf. which I believe is not a great way to handle it. But it is an option and maybe a first step instead of adding those functions?

coap_delete_bin_const(conf->id_context);
}

conf->id_context = id_context;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Unlikely that multiple threads are doing this concurrently, but this is not thread safe.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

coap_oscore_conf_set_context_id() has same return issue as coap_oscore_conf_set_snd(). Suggest things are fixed in the same way.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch 4 times, most recently from a4eb52a to 3fcadcf Compare April 6, 2026 13:16
Add reference counting to recipient contexts so they can be safely removed
while still in use by active sessions. Expose callback hooks for credential
lookup, echo, and sequence storage to allow custom backends.
Expand example server to demonstrate the external storage via a simple
file based database. Expand coap_oscore_conf_t with coap_oscore_rcp_conf_t
and coap_oscore_snd_conf_t with approproate setters to enable manipulation
after loading the oscore credentials.
Enable temporary credentials returned by the find function and are destroyed
after use.
@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch from 3fcadcf to 8eaadb6 Compare April 6, 2026 13:55
Copy link
Copy Markdown
Author

@BitFis BitFis left a comment

Choose a reason for hiding this comment

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

Resovled most comments, a few open with comments. I think you should be able to easily check that I resolved them as expected, but if not, will happily reopen and you can close them from your side.
Commits merged into one with updated commit message, feel free to comment.

for (i = 0; i < oscore_conf->recipient_id_count; i++) {
coap_delete_bin_const(oscore_conf->recipient_id[i]);
coap_delete_bin_const(oscore_conf->sender_id.sender_id);
coap_oscore_rcp_conf_t *current = oscore_conf->recipient_id;
Copy link
Copy Markdown
Author

@BitFis BitFis Apr 6, 2026

Choose a reason for hiding this comment

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

Had the same thought, but it will brake the file format / unclear how to manage in the parsing case:

CONFIG_ENTRY(sender_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),`

any ideas? Feels like breaking API change.

@BitFis BitFis requested a review from mrdeep1 April 6, 2026 14:04
Copy link
Copy Markdown
Collaborator

@mrdeep1 mrdeep1 left a comment

Choose a reason for hiding this comment

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

Some resolved re-opened.

@BitFis BitFis requested a review from mrdeep1 April 6, 2026 15:49
@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch from 2a68323 to 09718a2 Compare April 6, 2026 15:57
@BitFis BitFis force-pushed the feat/enable-external-oscore-credentials branch from 09718a2 to 9b9f445 Compare April 6, 2026 16:20
@mrdeep1
Copy link
Copy Markdown
Collaborator

mrdeep1 commented Apr 8, 2026

Please see #1952 for a backport from the libcoap OSCORE Group work to support complex sender / recipient configuration definitions.

I also note that several comments have not been resolved in the blocks of 'hidden conversations'.

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

Successfully merging this pull request may close these issues.

3 participants