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>