Provided by: libcoap3t64_4.3.4-1.1build4_amd64 bug

NAME

       coap_oscore, coap_oscore_is_supported, coap_new_oscore_conf, coap_delete_oscore_conf,
       coap_new_oscore_recipient, 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 - Work
       with CoAP OSCORE

SYNOPSIS

       #include <coap3/coap.h>

       int coap_oscore_is_supported(void);

       coap_oscore_conf_t *coap_new_oscore_conf(coap_str_const_t conf_mem, coap_oscore_save_seq_num_t
       save_seq_num_func, void *save_seq_num_func_param, uint64_t start_seq_num);

       int coap_delete_oscore_conf(coap_oscore_conf_t *oscore_conf);

       int coap_new_oscore_recipient(coap_context_t *context, coap_bin_const_t *recipient_id);

       int coap_delete_oscore_recipient(coap_context_t *context, coap_bin_const_t *recipient_id);

       coap_session_t *coap_new_client_session_oscore(coap_context_t *context, const coap_address_t *local_if,
       const coap_address_t *server, coap_proto_t proto, coap_oscore_conf_t *oscore_conf);

       coap_session_t *coap_new_client_session_oscore_psk(coap_context_t *context, const coap_address_t
       *local_if, const coap_address_t *server, coap_proto_t proto, coap_dtls_cpsk_t *psk_data,
       coap_oscore_conf_t *oscore_conf);

       coap_session_t *coap_new_client_session_oscore_pki(coap_context_t *context, const coap_address_t
       *local_if, const coap_address_t *server, coap_proto_t proto, coap_dtls_pki_t *pki_data,
       coap_oscore_conf_t *oscore_conf);

       int coap_context_oscore_server(coap_context_t *context, coap_oscore_conf_t *oscore_conf);

       For specific (D)TLS library support, link with -lcoap-3-notls, -lcoap-3-gnutls, -lcoap-3-openssl,
       -lcoap-3-mbedtls or -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default (D)TLS library
       support.

DESCRIPTION

       This describes libcoap’s support for using OSCORE as defined in RFC8613.

       OSCORE provides end-to-end protection between endpoints communicating using CoAP. (D)TLS can only protect
       HOP by HOP traffic which allows proxies to manipulate information.

CALLBACK HANDLER

       Callback Type: coap_oscore_save_seq_num_t

       The coap_oscore_save_seq_num_t method handler function prototype is defined as:

           typedef int (*coap_oscore_save_seq_num_t)(uint64_t sender_seq_num, void *param);

       and returns 0 on failure, 1 on succes.

FUNCTIONS

       Function: coap_oscore_is_supported()

       The coap_oscore_is_supported() function returns 1 if OSCORE is supported, otherwise 0.

       Function: coap_new_oscore_conf()

       The coap_new_oscore_conf() function is used to build a new OSCORE configuration. It parses the provided
       OSCORE configuration in conf_mem. The format of the keywords, encoding types and values is documented in
       coap-oscore-conf(5). It also sets an optional function save_seq_num_func (which gets
       save_seq_num_func_param passed in) that is called to store the next Sender Sequence Number (SSN) in
       non-volatile storage. The latest next SSN from non-volatile storage (or 0) is then put in start_seq_num.
       SSN are used so that anti-replay mechanisms do not kick in following application restarts. The rate of
       calling save_seq_num_func can be controlled by the ssn_freq parameter as defined in coap-oscore-conf(5).

       This OSCORE configuration is then used in the client and server OSCORE version of the setup functions.

       If the server is proxy enabled and the new incoming session is OSCORE encoded with the Outer CoAP
       ProxyScheme and Host options set, then the libcoap logic will determine whether the server is the final
       endpoint of the session, or whether the proxy will be forwarding the session off to another server, based
       on how coap_resource_proxy_uri_init(3) configured the proxy logic. If the session is going to forwarded,
       then the OSCORE protection will not be removed.

       If coap_context_oscore_server() is not called and the proxy logic (if set) indicates the session will get
       forwarded, then the OSCORE protection is untouched, otherwise the session will get dropped with an
       unknown critical option error response.

       Function: coap_new_oscore_recipient()

       The coap_new_oscore_recipient() is used to add a new recipient_id to the OSCORE information associated
       with context. The new recipient_id should be unique and this function should only be used for server
       based applications as the client will only ever use the first defined recipient_id. It is assumed that
       coap_context_oscore_server() has already been called to update context with the appropriate OSCORE
       information.

       Function: coap_delete_oscore_recipient()

       The coap_delete_oscore_recipient() is used to remove the recipient_id from the OSCORE information
       associated with context. OSCORE Traffic continuing to use recipient_id will then fail.

       Function: coap_delete_oscore_conf()

       The coap_delete_oscore_conf() function is used to free off the coap_oscore_conf_t structure oscore_conf
       as returned by coap_new_oscore_conf(). Normally this function never needs to be called as oscore_conf is
       freed off by the call the client or server setup functions.

       Function: coap_new_client_session_oscore()

       The coap_new_client_session_oscore() is basically the same as coap_new_client_session(3), but has an
       additional parameter oscore_conf that is created by coap_new_oscore_conf(). This function creates a
       client endpoint for a specific context and initiates a new client session to the specified server using
       the CoAP protocol proto and OSCORE protected by the oscore_conf definition (which is freed off by this
       call). If the port is set to 0 in server, then the default CoAP port is used. Normally local_if would be
       set to NULL, but by specifying local_if the source of the network session can be bound to a specific IP
       address or port. The session will initially have a reference count of 1.

       Function: coap_new_client_session_oscore_psk()

       The coap_new_client_session_oscore_psk() is basically the same as coap_new_client_session_psk2(3), but
       has an additional parameter oscore_conf that is created by coap_new_oscore_conf(). This function, for a
       specific context, is used to configure the TLS context using the setup_data variables as defined in the
       coap_dtls_cpsk_t structure in the newly created endpoint session - see coap_encryption(3), as well as
       OSCORE protected by the oscore_conf definition (which is freed off by this call). The connection is to
       the specified server using the CoAP protocol proto. If the port is set to 0 in server, then the default
       CoAP port is used. Normally local_if would be set to NULL, but by specifying local_if the source of the
       network session can be bound to a specific IP address or port. The session will initially have a
       reference count of 1.

       Function: coap_new_client_session_oscore_pki()

       The coap_new_client_session_oscore_pki() is basically the same as coap_new_client_session_pki(3), but has
       an additional parameter oscore_conf that is created by coap_new_oscore_conf(). This function, for a
       specific context, is used to configure the TLS context using the setup_data variables as defined in the
       coap_dtls_pki_t structure in the newly created endpoint session - see coap_encryption(3), as well as
       OSCORE protected by the oscore_conf definition (which is freed off by this call). The connection is to
       the specified server using the CoAP protocol proto. If the port is set to 0 in server, then the default
       CoAP port is used. Normally local_if would be set to NULL, but by specifying local_if the source of the
       network session can be bound to a specific IP address or port. The session will initially have a
       reference count of 1.

       Function: coap_context_oscore_server()

       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).

RETURN VALUES

       coap_new_client_session_oscore(), coap_new_client_session_oscore_psk() and
       coap_new_client_session_oscore_pki() return a newly created client session or NULL if there is a malloc
       or parameter failure.

       coap_new_oscore_conf() returns a coap_oscore_conf_t or NULL on failure.

       coap_oscore_is_supported(), coap_context_oscore_server(), coap_delete_oscore_conf(),
       coap_new_oscore_recipient() and coap_delete_oscore_recipient() return 0 on failure, 1 on success.

EXAMPLES

       Client Setup

           #include <coap3/coap.h>

           #include <netinet/in.h>
           #include <stdio.h>

           static uint8_t oscore_config[] =
             "master_secret,hex,\"0102030405060708090a0b0c0d0e0f10\"\n"
             "master_salt,hex,\"9e7ca92223786340\"\n"
             "server_id,ascii,\"client\"\n"
             "recipient_id,ascii,\"server\"\n"
             "replay_window,integer,30\n"
             "aead_alg,integer,10\n"
             "hkdf_alg,integer,-10\n"
           ;
           static FILE *oscore_seq_num_fp = NULL;
           /* Not a particularly safe place to keep next Sender Sequence Number ... */
           static const char* oscore_seq_save_file = "/tmp/client.seq";

           static int
           oscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) {
             if (oscore_seq_num_fp) {
               rewind(oscore_seq_num_fp);
               fprintf(oscore_seq_num_fp, "%lu\n", sender_seq_num);
               fflush(oscore_seq_num_fp);
             }
             return 1;
           }

           static coap_session_t *
           setup_client_session (struct in_addr ip_address) {
             coap_session_t *session;
             coap_address_t server;
             /* See coap_context(3) */
             coap_context_t *context = coap_new_context(NULL);

             if (!context)
               return NULL;

             /* See coap_block(3) */
             coap_context_set_block_mode(context,
                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

             coap_address_init(&server);
             server.addr.sa.sa_family = AF_INET;
             server.addr.sin.sin_addr = ip_address;
             server.addr.sin.sin_port = htons (5683);

             if (coap_oscore_is_supported()) {
               coap_str_const_t config = { sizeof (oscore_config), oscore_config };
               uint64_t start_seq_num = 0;
               coap_oscore_conf_t *oscore_conf;

               if (oscore_seq_save_file) {
                 oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+");
                 if (oscore_seq_num_fp == NULL) {
                   /* Try creating it */
                   oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+");
                   if (oscore_seq_num_fp == NULL) {
                     coap_log_err("OSCORE save restart info file error: %s\n",
                              oscore_seq_save_file);
                     return NULL;
                   }
                 }
                 fscanf(oscore_seq_num_fp, "%ju", &start_seq_num);
               }
               oscore_conf = coap_new_oscore_conf(config, oscore_save_seq_num,
                                                  NULL, start_seq_num);
               if (!oscore_conf) {
                 coap_free_context(context);
                 return NULL;
               }
               session = coap_new_client_session_oscore(context, NULL, &server,
                                                        COAP_PROTO_UDP, oscore_conf);
             } else {
               session = coap_new_client_session(context, NULL, &server, COAP_PROTO_UDP);
             }
             if (!session) {
               coap_free_context(context);
               return NULL;
             }
             /* The context is in session->context */
             return session;
           }

       Server Setup

           #include <coap3/coap.h>
           #include <stdio.h>

           static uint8_t oscore_config[] =
             "master_secret,hex,\"0102030405060708090a0b0c0d0e0f10\"\n"
             "master_salt,hex,\"9e7ca92223786340\"\n"
             "sender_id,ascii,\"server\"\n"
             "recipient_id,ascii,\"client\"\n"
             "replay_window,integer,30\n"
             "aead_alg,integer,10\n"
             "hkdf_alg,integer,-10\n"
           ;
           static FILE *oscore_seq_num_fp = NULL;
           /* Not a particularly safe place to keep next Sender Sequence Number ... */
           static const char* oscore_seq_save_file = "/tmp/server.seq";

           static int
           oscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) {
             if (oscore_seq_num_fp) {
               rewind(oscore_seq_num_fp);
               fprintf(oscore_seq_num_fp, "%lu\n", sender_seq_num);
               fflush(oscore_seq_num_fp);
             }
             return 1;
           }

           static int
           setup_context (void) {
             /* See coap_context(3) */
             coap_context_t *context = coap_new_context(NULL);

             if (!context)
               return 0;

             /* See coap_block(3) */
             coap_context_set_block_mode(context,
                                         COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY);

             if (coap_oscore_is_supported()) {
               coap_str_const_t config = { sizeof (oscore_config), oscore_config };
               uint64_t start_seq_num = 0;
               coap_oscore_conf_t *oscore_conf;

               if (oscore_seq_save_file) {
                 oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+");
                 if (oscore_seq_num_fp == NULL) {
                   /* Try creating it */
                   oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+");
                   if (oscore_seq_num_fp == NULL) {
                     coap_log_err("OSCORE save restart info file error: %s\n",
                              oscore_seq_save_file);
                     return 0;
                   }
                 }
                 fscanf(oscore_seq_num_fp, "%ju", &start_seq_num);
               }
               oscore_conf = coap_new_oscore_conf(config, oscore_save_seq_num,
                                                  NULL, start_seq_num);
               if (!oscore_conf) {
                 coap_free_context(context);
                 return 0;
               }
               coap_context_oscore_server(context, oscore_conf);
             }
             return 1;
           }

SEE ALSO

       coap_endpoint_client(3), coap_endpoint_server(3) and coap-oscore-conf(5)

FURTHER INFORMATION

       See

       "RFC7252: The Constrained Application Protocol (CoAP)"

       "RFC8613: Object Security for Constrained RESTful Environments (OSCORE)"

       for further information.

BUGS

       Please report bugs on the mailing list for libcoap: libcoap-developers@lists.sourceforge.net or raise an
       issue on GitHub at https://github.com/obgm/libcoap/issues

AUTHORS

       The libcoap project <libcoap-developers@lists.sourceforge.net>