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

OSCORE: Added user-defined callback for finding oscore context #1331

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/coap3/coap_net_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ struct coap_context_t {
#endif /* WITH_LWIP */
#if COAP_OSCORE_SUPPORT
struct oscore_ctx_t *p_osc_ctx; /**< primary oscore context */
external_oscore_find_context_handler_t external_oscore_find_context_handler;
/**< Called when oscore_find_context didn't find any context*/
#endif /* COAP_OSCORE_SUPPORT */

#if COAP_CLIENT_SUPPORT
Expand Down
46 changes: 45 additions & 1 deletion include/coap3/coap_oscore.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,17 @@ int coap_context_oscore_server(coap_context_t *context,
*
* @param sender_seq_num The Sender Sequence Number to save in non-volatile
* memory.
* @param recipient_id Recipient ID that could be used to find the corresponding SSN entry.
* @param id_context ID Context that could be used to find the corresponding SSN entry.
* @param param The save_seq_num_func_param provided to
* coap_new_oscore_context().
*
* @return @c 1 if success, else @c 0 if a failure of some sort.
*/
typedef int (*coap_oscore_save_seq_num_t)(uint64_t sender_seq_num, void *param);
typedef int (*coap_oscore_save_seq_num_t)(uint64_t sender_seq_num,
const coap_bin_const_t *recipient_id,
const coap_bin_const_t *id_context,
void *param);
Comment on lines -137 to +142
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is a change to the Public API which we do not want to have to do unless it is absolutely critical.

My suggestion would be to add in save (and delete) function parameters to coap_register_oscore_context_handler() and call those functions in the appropriate points in the code. Then from a user perspective, everything is in one place for doing the definitions.

Update coap_context-t to include something similar to external_oscore_update_context_handler and external_oscore_delete_context_handler.


/**
* Parse an OSCORE configuration (held in memory) and populate a OSCORE
Expand Down Expand Up @@ -193,6 +198,45 @@ int coap_new_oscore_recipient(coap_context_t *context,
int coap_delete_oscore_recipient(coap_context_t *context,
coap_bin_const_t *recipient_id);

/**
* Opaque pointer for internal oscore_ctx_t type.
*/
typedef struct oscore_ctx_t * oscore_ctx_handle_t;

/**
* Opaque pointer for internal oscore_recipient_ctx_t type.
*
*/
typedef struct oscore_recipient_ctx_t * oscore_recipient_ctx_handle_t;
Comment on lines +201 to +210
Copy link
Collaborator

Choose a reason for hiding this comment

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

In general for libcoap, all the other typedef struct X X; statements do not have the * (pointer) included. We need to be consistent here.

In general, any forward declarations should be included in the appropriate place in include/coap3/coap_forward_decls.h.

As we are trying to keep the public API to have everything prefixed with coap_ to prevent any name clashes, I think perhaps the 2 forward references (in include/coap3/coap_forward_decls.h) should be

typedef struct oscore_ctx_t coap_oscore_handle_t
typedef struct oscore_recipient_ctx_t coap_oscore_recipient_ctx_handle_t

and then referenced in your changes with the new names.


/**
* Optional user callback to be used, when oscore_find_context can't find any context.
* Could be used to check external storage (e.g. FLASH).
*
* @param c_context The CoAP Context to search.
* @param rcpkey_id The Recipient kid.
* @param ctxkey_id The ID Context to match (or NULL if no check).
* @param oscore_r2 Partial id_context to match against or NULL.
* @param recipient_ctx The recipient context to update.
*
* return The OSCORE context and @p recipient_ctx updated, or NULL is error.
*/
typedef oscore_ctx_handle_t (*external_oscore_find_context_handler_t)(
const coap_context_t *c_context,
const coap_bin_const_t rcpkey_id,
const coap_bin_const_t *ctxkey_id,
uint8_t *oscore_r2,
oscore_recipient_ctx_handle_t *recipient_ctx);

/**
* Register optional user callback to be used, when oscore_find_context can't find any context.
* Callback could be used to check external storage (e.g. FLASH).
*
* @param context The current coap context to use.
* @param handler User callback.
*/
void coap_register_oscore_context_handler(coap_context_t *context, external_oscore_find_context_handler_t handler);
Copy link
Collaborator

Choose a reason for hiding this comment

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

As mentioned previously, this should include an add/update handler as well as possibly a delete handler. Even if delete is not currently used, it is a placeholder that will not break the API with that as a change.


/** @} */

#endif /* COAP_OSCORE_H */
11 changes: 11 additions & 0 deletions include/coap3/coap_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
* @{
*/

#include <stdbool.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

For historical reasons that I cant recall, it was decided that there should not be the use of boolean in the libcoap code, so this should not be used.


/**
* Abstraction of a fixed point number that can be used where necessary instead
* of a float. 1,000 fractional bits equals one integer
Expand Down Expand Up @@ -163,6 +165,15 @@ coap_proto_t coap_session_get_proto(const coap_session_t *session);
*/
coap_session_type_t coap_session_get_type(const coap_session_t *session);

/**
* Check if CoAP session is encrypted.
*
* @param session The CoAP session.
*
* @return True if session is encrypted, false if session is not encrypted.
*/
bool coap_session_is_encrypted(const coap_session_t *session);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use int instead of bool, and document return value accordingly.


/**
* Get the session state
*
Expand Down
17 changes: 17 additions & 0 deletions include/oscore/oscore_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,23 @@ oscore_ctx_t *oscore_find_context(const coap_context_t *c_context,
uint8_t *oscore_r2,
oscore_recipient_ctx_t **recipient_ctx);

/**
* oscore_find_context_in_ram - Locate recipient context (and hence OSCORE context) in RAM only
*
* @param c_context The CoAP Context to search.
* @param rcpkey_id The Recipient kid.
* @param ctxkey_id The ID Context to match (or NULL if no check).
* @param oscore_r2 Partial id_context to match against or NULL.
* @param recipient_ctx The recipient context to update.
*
* return The OSCORE context and @p recipient_ctx updated, or NULL is error.
*/
oscore_ctx_t *oscore_find_context_in_ram(const coap_context_t *c_context,
const coap_bin_const_t rcpkey_id,
const coap_bin_const_t *ctxkey_id,
uint8_t *oscore_r2,
oscore_recipient_ctx_t **recipient_ctx);

void oscore_free_association(oscore_association_t *association);

int oscore_new_association(coap_session_t *session,
Expand Down
17 changes: 16 additions & 1 deletion man/coap_oscore.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ coap_delete_oscore_recipient,
coap_new_client_session_oscore,
coap_new_client_session_oscore_pki,
coap_new_client_session_oscore_psk,
coap_context_oscore_server
coap_context_oscore_server,
coap_register_oscore_context_handler
Copy link
Collaborator

Choose a reason for hiding this comment

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

As you may have discovered, you will need to add in an entry line into man/Makefile.am

        @echo ".so man3/coap_oscore.3" > coap_context_oscore_server.3
+      @echo ".so man3/coap_oscore.3" > coap_register_oscore_context_handler.3
        @echo ".so man3/coap_pdu_access.3" > coap_option_filter_set.3

- Work with CoAP OSCORE

SYNOPSIS
Expand Down Expand Up @@ -57,6 +58,9 @@ coap_oscore_conf_t *_oscore_conf_);*
*int coap_context_oscore_server(coap_context_t *_context_,
coap_oscore_conf_t *_oscore_conf_);*

*void coap_register_oscore_context_handler(coap_context_t *context,
external_oscore_find_context_handler_t handler);*

For specific (D)TLS library support, link with
*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*,
*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls*
Expand Down Expand Up @@ -191,6 +195,17 @@ The *coap_context_oscore_server*() function is used to enable the server to
support OSCORE incoming sessions. It updates _context_ with the OSCORE
configure _oscore_conf_ (which is freed off by this call).

*Function: coap_register_oscore_context_handler()*

The *coap_register_oscore_context_handler*() function is used to register
an optional, external callback, which will be called if no OSCORE context
is found by oscore_find_context. It can be used by the user to provide an
external source of OSCORE contexts, e.g. a non-volatile memory.
Together with user-defined coap_oscore_save_seq_num_t callback provided
while creating the context, this mechanism may be used to periodically
store Sender Sequence Number field - thus providing a way to fully restore
the context after the device reboots.
Comment on lines +200 to +207
Copy link
Collaborator

Choose a reason for hiding this comment

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

Will need to get updated to include add/update, delete functions.


RETURN VALUES
-------------
*coap_new_client_session_oscore*(), *coap_new_client_session_oscore_psk*()
Expand Down
7 changes: 7 additions & 0 deletions man/coap_session.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ coap_session_get_proto,
coap_session_get_state,
coap_session_get_tls,
coap_session_get_type,
coap_session_is_encrypted,
Copy link
Collaborator

Choose a reason for hiding this comment

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

As you may have discovered, you will need to add in an entry line into man/Makefile.am

        @echo ".so man3/coap_session.3" > coap_session_get_type.3
+      @echo ".so man3/coap_session.3" > coap_session_is_encrypted.3
        @echo ".so man3/coap_string.3" > coap_delete_bin_const.3

I would also prefer to see this entry at the end of the list, after the set/get functions.

coap_session_get_psk_hint,
coap_session_get_psk_key
- Work with CoAP sessions
Expand Down Expand Up @@ -68,6 +69,8 @@ coap_tls_library_t *tls_lib);*

*coap_session_type_t coap_session_get_type(const coap_session_t *_session_);*

*bool coap_session_is_encrypted(const coap_session_t *session);*
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use int instead of bool.


*const coap_bin_const_t *coap_session_get_psk_hint(
const coap_session_t *_session_);*

Expand Down Expand Up @@ -216,6 +219,8 @@ COAP_SESSION_TYPE_HELLO /* Negotiating a (D)TLS session */
The *coap_session_get_type*() function is used to get the session type from the
_session_.

The *coap_session_is_encrypted*() function is used to check if incoming _session_ is encrypted.

Comment on lines +222 to +223
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should be moved to after the get functions.

The *coap_session_get_psk_hint*() function is used to get the current server
_session_'s pre-shared-key identity hint.

Expand Down Expand Up @@ -253,6 +258,8 @@ error.

*coap_session_get_type*() returns the current session's type or 0 on error.

*coap_session_is_encrypted*() returns true if the session is using OSCORE encryption, or false if plain CoAP packets are used.

Comment on lines +261 to +262
Copy link
Collaborator

Choose a reason for hiding this comment

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

Correct return types not to be boolean. Also, move this to after the get functions.

*coap_session_get_psk_hint*() returns the current server session's
pre-shared-key identity hint, or NULL if not defined.

Expand Down
4 changes: 3 additions & 1 deletion src/coap_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,9 @@ coap_option_check_critical(coap_session_t *session,
case COAP_OPTION_OSCORE:
/* Valid critical if doing OSCORE */
#if COAP_OSCORE_SUPPORT
if (ctx->p_osc_ctx)
/* Only accept OSCORE option if any OSCORE context is available,
or the user provided an external handler for finding the context. */
if ((ctx->p_osc_ctx) || (ctx->external_oscore_find_context_handler))
break;
#endif /* COAP_OSCORE_SUPPORT */
/* Fall Through */
Expand Down
21 changes: 20 additions & 1 deletion src/coap_oscore.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,8 @@ coap_oscore_new_pdu_encrypted(coap_session_t *session,
/* Only update at ssn_freq rate */
osc_ctx->sender_context->next_seq += osc_ctx->ssn_freq;
osc_ctx->save_seq_num_func(osc_ctx->sender_context->next_seq,
rcp_ctx->recipient_id,
osc_ctx->id_context,
Comment on lines +406 to +407
Copy link
Collaborator

Choose a reason for hiding this comment

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

Unfortunately this breaks the public API - See previous comments.

osc_ctx->save_seq_num_func_param);
}
}
Expand Down Expand Up @@ -808,7 +810,10 @@ coap_oscore_decrypt_pdu(coap_session_t *session,
if (opt == NULL)
return NULL;

if (session->context->p_osc_ctx == NULL) {
/* OSCORE should be processed only if any OSCORE context is available,
or the user provided an external handler for finding the context. */
if ((session->context->p_osc_ctx == NULL) &&
(session->context->external_oscore_find_context_handler == NULL)) {
coap_log_warn("OSCORE: Not enabled\n");
if (!coap_request)
coap_handle_event(session->context,
Expand Down Expand Up @@ -2106,6 +2111,13 @@ coap_delete_oscore_recipient(coap_context_t *context,
return oscore_delete_recipient(context->p_osc_ctx, recipient_id);
}

void
coap_register_oscore_context_handler(coap_context_t *context, external_oscore_find_context_handler_t handler)
{
assert(context);
context->external_oscore_find_context_handler = handler;
}

/** @} */

#else /* !COAP_OSCORE_SUPPORT */
Expand Down Expand Up @@ -2202,4 +2214,11 @@ coap_delete_oscore_recipient(coap_context_t *context,
return 0;
}

void
coap_register_oscore_context_handler(coap_context_t *context, external_oscore_find_context_handler_t handler)
{
(void)context;
(void)handler;
}

#endif /* !COAP_OSCORE_SUPPORT */
8 changes: 8 additions & 0 deletions src/coap_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,14 @@ coap_session_get_type(const coap_session_t *session) {
return 0;
}

bool
coap_session_is_encrypted(const coap_session_t *session) {
#if COAP_OSCORE_SUPPORT
return (session->oscore_encryption != 0);
#endif
return false;
}

#if COAP_CLIENT_SUPPORT
int
coap_session_set_type_client(coap_session_t *session) {
Expand Down
26 changes: 26 additions & 0 deletions src/oscore/oscore_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,32 @@ oscore_find_context(const coap_context_t *c_context,
const coap_bin_const_t *ctxkey_id,
uint8_t *oscore_r2,
oscore_recipient_ctx_t **recipient_ctx) {
oscore_ctx_t *osc_ctx = oscore_find_context_in_ram(c_context, rcpkey_id, ctxkey_id, oscore_r2, recipient_ctx);
if( NULL != osc_ctx )
{
return osc_ctx;
}

/* no context was found in libcoap RAM - call user function to also check external storage (e.g. FLASH) */
if (c_context->external_oscore_find_context_handler)
{
return c_context->external_oscore_find_context_handler(c_context, rcpkey_id, ctxkey_id, oscore_r2, recipient_ctx);
}
return NULL;
}

/*
* oscore_find_context_in_ram
* Finds OSCORE context in RAM for rcpkey_id and optional ctxkey_id
* rcpkey_id can be 0 length.
* Updates recipient_ctx.
*/
oscore_ctx_t *
oscore_find_context_in_ram(const coap_context_t *c_context,
const coap_bin_const_t rcpkey_id,
const coap_bin_const_t *ctxkey_id,
uint8_t *oscore_r2,
oscore_recipient_ctx_t **recipient_ctx) {
oscore_ctx_t *pt = c_context->p_osc_ctx;

*recipient_ctx = NULL;
Expand Down
Loading