1// -*- mode:doc; -*- 2// vim: set syntax=asciidoc tw=0 3 4coap_oscore(3) 5============== 6:doctype: manpage 7:man source: coap_oscore 8:man version: @PACKAGE_VERSION@ 9:man manual: libcoap Manual 10 11NAME 12---- 13coap_oscore, 14coap_oscore_is_supported, 15coap_new_oscore_conf, 16coap_delete_oscore_conf, 17coap_new_oscore_recipient, 18coap_delete_oscore_recipient, 19coap_new_client_session_oscore, 20coap_new_client_session_oscore_pki, 21coap_new_client_session_oscore_psk, 22coap_context_oscore_server 23- Work with CoAP OSCORE 24 25SYNOPSIS 26-------- 27*#include <coap@LIBCOAP_API_VERSION@/coap.h>* 28 29*int coap_oscore_is_supported(void);* 30 31*coap_oscore_conf_t *coap_new_oscore_conf(coap_str_const_t _conf_mem_, 32coap_oscore_save_seq_num_t _save_seq_num_func_, 33void *_save_seq_num_func_param_, uint64_t _start_seq_num_);* 34 35*int coap_delete_oscore_conf(coap_oscore_conf_t *_oscore_conf_);* 36 37*int coap_new_oscore_recipient(coap_context_t *_context_, 38coap_bin_const_t *_recipient_id_);* 39 40*int coap_delete_oscore_recipient(coap_context_t *_context_, 41coap_bin_const_t *_recipient_id_);* 42 43*coap_session_t *coap_new_client_session_oscore(coap_context_t *_context_, 44const coap_address_t *_local_if_, const coap_address_t *_server_, 45coap_proto_t _proto_, coap_oscore_conf_t *_oscore_conf_);* 46 47*coap_session_t *coap_new_client_session_oscore_psk(coap_context_t *_context_, 48const coap_address_t *_local_if_, const coap_address_t *_server_, 49coap_proto_t _proto_, coap_dtls_cpsk_t *_psk_data_, 50coap_oscore_conf_t *_oscore_conf_);* 51 52*coap_session_t *coap_new_client_session_oscore_pki(coap_context_t *_context_, 53const coap_address_t *_local_if_, const coap_address_t *_server_, 54coap_proto_t _proto_, coap_dtls_pki_t *_pki_data_, 55coap_oscore_conf_t *_oscore_conf_);* 56 57*int coap_context_oscore_server(coap_context_t *_context_, 58coap_oscore_conf_t *_oscore_conf_);* 59 60For specific (D)TLS library support, link with 61*-lcoap-@LIBCOAP_API_VERSION@-notls*, *-lcoap-@LIBCOAP_API_VERSION@-gnutls*, 62*-lcoap-@LIBCOAP_API_VERSION@-openssl*, *-lcoap-@LIBCOAP_API_VERSION@-mbedtls* 63or *-lcoap-@LIBCOAP_API_VERSION@-tinydtls*. Otherwise, link with 64*-lcoap-@LIBCOAP_API_VERSION@* to get the default (D)TLS library support. 65 66DESCRIPTION 67----------- 68This describes libcoap's support for using OSCORE as defined in 69https://rfc-editor.org/rfc/rfc8613[RFC8613]. 70 71OSCORE provides end-to-end protection between endpoints communicating using 72CoAP. (D)TLS can only protect HOP by HOP traffic which allows proxies to 73manipulate information. 74 75CALLBACK HANDLER 76---------------- 77 78*Callback Type: coap_oscore_save_seq_num_t* 79 80The coap_oscore_save_seq_num_t method handler function prototype is defined as: 81[source, c] 82---- 83typedef int (*coap_oscore_save_seq_num_t)(uint64_t sender_seq_num, void *param); 84---- 85and returns 0 on failure, 1 on succes. 86 87FUNCTIONS 88--------- 89 90*Function: coap_oscore_is_supported()* 91 92The *coap_oscore_is_supported*() function returns 1 if OSCORE is supported, 93otherwise 0. 94 95*Function: coap_new_oscore_conf()* 96 97The *coap_new_oscore_conf*() function is used to build a new OSCORE 98configuration. It parses the provided OSCORE configuration 99in _conf_mem_. The format of the keywords, encoding types and values is 100documented in *coap-oscore-conf*(5). It also sets an optional function 101_save_seq_num_func_ (which gets _save_seq_num_func_param_ passed in) that is 102called to store the next Sender Sequence Number (SSN) in non-volatile 103storage. The latest next SSN from non-volatile storage (or 0) is then put in 104_start_seq_num_. SSN are used so that anti-replay mechanisms do not kick in 105following application restarts. The rate of calling _save_seq_num_func_ can 106be controlled by the _ssn_freq_ parameter as defined in *coap-oscore-conf*(5). 107 108This OSCORE configuration is then used in the client and server OSCORE version 109of the setup functions. 110 111If the server is proxy enabled and the new incoming session is OSCORE encoded 112with the Outer CoAP ProxyScheme and Host options set, then the libcoap logic 113will determine whether the server is the final endpoint of the session, or 114whether the proxy will be forwarding the session off to another server, based 115on how *coap_resource_proxy_uri_init*(3) configured the proxy logic. If the 116session is going to forwarded, then the OSCORE protection will not be removed. 117 118If *coap_context_oscore_server*() is not called and the proxy logic (if set) 119indicates the session will get forwarded, then the OSCORE protection is 120untouched, otherwise the session will get dropped with an unknown critical 121option error response. 122 123*Function: coap_new_oscore_recipient()* 124 125The *coap_new_oscore_recipient*() is used to add a new _recipient_id_ to the 126OSCORE information associated with _context_. The new _recipient_id_ should 127be unique and this function should only be used for server based applications 128as the client will only ever use the first defined _recipient_id_. It is 129assumed that *coap_context_oscore_server*() has already been called to update 130_context_ with the appropriate OSCORE information. 131 132*Function: coap_delete_oscore_recipient()* 133 134The *coap_delete_oscore_recipient*() is used to remove the _recipient_id_ from 135the OSCORE information associated with _context_. OSCORE Traffic continuing 136to use _recipient_id_ will then fail. 137 138*Function: coap_delete_oscore_conf()* 139 140The *coap_delete_oscore_conf*() function is used to free off the 141coap_oscore_conf_t structure _oscore_conf_ as returned by 142*coap_new_oscore_conf*(). Normally this function never needs to be called 143as _oscore_conf_ is freed off by the call the client or server setup functions. 144 145*Function: coap_new_client_session_oscore()* 146 147The *coap_new_client_session_oscore*() is basically the same as 148*coap_new_client_session*(3), but has an additional parameter _oscore_conf_ 149that is created by *coap_new_oscore_conf*(). This function creates a 150client endpoint for a specific _context_ and initiates a new client session 151to the specified _server_ using the CoAP protocol _proto_ and OSCORE 152protected by the _oscore_conf_ definition (which is freed off by this call). 153If the port is set to 0 in _server_, then the default CoAP port is used. 154Normally _local_if_ would be set to NULL, but by specifying _local_if_ the 155source of the network session can be bound to a specific IP address or port. 156The session will initially have a reference count of 1. 157 158*Function: coap_new_client_session_oscore_psk()* 159 160The *coap_new_client_session_oscore_psk*() is basically the same as 161*coap_new_client_session_psk2*(3), but has an additional parameter 162_oscore_conf_ that is created by *coap_new_oscore_conf*(). This 163function, for a specific _context_, is used to configure the TLS context 164using the _setup_data_ variables as defined in the coap_dtls_cpsk_t structure 165in the newly created endpoint session - see *coap_encryption*(3), 166as well as OSCORE protected by the _oscore_conf_ definition (which is freed 167off by this call). The connection is to the specified _server_ using the CoAP 168protocol _proto_. If the port is set to 0 in _server_, then the default CoAP 169port is used. Normally _local_if_ would be set to NULL, but by specifying 170_local_if_ the source of the network session can be bound to a specific IP 171address or port. The session will initially have a reference count of 1. 172 173*Function: coap_new_client_session_oscore_pki()* 174 175The *coap_new_client_session_oscore_pki*() is basically the same as 176*coap_new_client_session_pki*(3), but has an additional parameter 177_oscore_conf_ that is created by *coap_new_oscore_conf*(). This 178function, for a specific _context_, is used to configure the TLS context using 179the _setup_data_ variables as defined in the coap_dtls_pki_t structure in the 180newly created endpoint session - see *coap_encryption*(3), as well as OSCORE 181protected by the _oscore_conf_ definition (which is freed off by this call). 182The connection is to the specified _server_ using the CoAP protocol _proto_. 183If the port is set to 0 in _server_, then the default CoAP port is used. 184Normally _local_if_ would be set to NULL, but by specifying _local_if_ the 185source of the network session can be bound to a specific IP address or port. 186The session will initially have a reference count of 1. 187 188*Function: coap_context_oscore_server()* 189 190The *coap_context_oscore_server*() function is used to enable the server to 191support OSCORE incoming sessions. It updates _context_ with the OSCORE 192configure _oscore_conf_ (which is freed off by this call). 193 194RETURN VALUES 195------------- 196*coap_new_client_session_oscore*(), *coap_new_client_session_oscore_psk*() 197and *coap_new_client_session_oscore_pki*() return a newly created 198client session or NULL if there is a malloc or parameter failure. 199 200*coap_new_oscore_conf*() returns a _coap_oscore_conf_t_ 201or NULL on failure. 202 203*coap_oscore_is_supported*(), *coap_context_oscore_server*(), 204*coap_delete_oscore_conf*(), *coap_new_oscore_recipient*() and 205*coap_delete_oscore_recipient*() return 0 on failure, 1 on success. 206 207EXAMPLES 208-------- 209*Client Setup* 210 211[source, c] 212---- 213#include <coap@LIBCOAP_API_VERSION@/coap.h> 214 215#include <netinet/in.h> 216#include <stdio.h> 217 218static uint8_t oscore_config[] = 219 "master_secret,hex,\"0102030405060708090a0b0c0d0e0f10\"\n" 220 "master_salt,hex,\"9e7ca92223786340\"\n" 221 "server_id,ascii,\"client\"\n" 222 "recipient_id,ascii,\"server\"\n" 223 "replay_window,integer,30\n" 224 "aead_alg,integer,10\n" 225 "hkdf_alg,integer,-10\n" 226; 227static FILE *oscore_seq_num_fp = NULL; 228/* Not a particularly safe place to keep next Sender Sequence Number ... */ 229static const char* oscore_seq_save_file = "/tmp/client.seq"; 230 231static int 232oscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) { 233 if (oscore_seq_num_fp) { 234 rewind(oscore_seq_num_fp); 235 fprintf(oscore_seq_num_fp, "%lu\n", sender_seq_num); 236 fflush(oscore_seq_num_fp); 237 } 238 return 1; 239} 240 241static coap_session_t * 242setup_client_session (struct in_addr ip_address) { 243 coap_session_t *session; 244 coap_address_t server; 245 /* See coap_context(3) */ 246 coap_context_t *context = coap_new_context(NULL); 247 248 if (!context) 249 return NULL; 250 251 /* See coap_block(3) */ 252 coap_context_set_block_mode(context, 253 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 254 255 256 coap_address_init(&server); 257 server.addr.sa.sa_family = AF_INET; 258 server.addr.sin.sin_addr = ip_address; 259 server.addr.sin.sin_port = htons (5683); 260 261 if (coap_oscore_is_supported()) { 262 coap_str_const_t config = { sizeof (oscore_config), oscore_config }; 263 uint64_t start_seq_num = 0; 264 coap_oscore_conf_t *oscore_conf; 265 266 if (oscore_seq_save_file) { 267 oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+"); 268 if (oscore_seq_num_fp == NULL) { 269 /* Try creating it */ 270 oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+"); 271 if (oscore_seq_num_fp == NULL) { 272 coap_log_err("OSCORE save restart info file error: %s\n", 273 oscore_seq_save_file); 274 return NULL; 275 } 276 } 277 fscanf(oscore_seq_num_fp, "%ju", &start_seq_num); 278 } 279 oscore_conf = coap_new_oscore_conf(config, oscore_save_seq_num, 280 NULL, start_seq_num); 281 if (!oscore_conf) { 282 coap_free_context(context); 283 return NULL; 284 } 285 session = coap_new_client_session_oscore(context, NULL, &server, 286 COAP_PROTO_UDP, oscore_conf); 287 } else { 288 session = coap_new_client_session(context, NULL, &server, COAP_PROTO_UDP); 289 } 290 if (!session) { 291 coap_free_context(context); 292 return NULL; 293 } 294 /* The context is in session->context */ 295 return session; 296} 297---- 298 299*Server Setup* 300 301[source, c] 302---- 303#include <coap@LIBCOAP_API_VERSION@/coap.h> 304#include <stdio.h> 305 306static uint8_t oscore_config[] = 307 "master_secret,hex,\"0102030405060708090a0b0c0d0e0f10\"\n" 308 "master_salt,hex,\"9e7ca92223786340\"\n" 309 "sender_id,ascii,\"server\"\n" 310 "recipient_id,ascii,\"client\"\n" 311 "replay_window,integer,30\n" 312 "aead_alg,integer,10\n" 313 "hkdf_alg,integer,-10\n" 314; 315static FILE *oscore_seq_num_fp = NULL; 316/* Not a particularly safe place to keep next Sender Sequence Number ... */ 317static const char* oscore_seq_save_file = "/tmp/server.seq"; 318 319static int 320oscore_save_seq_num(uint64_t sender_seq_num, void *param COAP_UNUSED) { 321 if (oscore_seq_num_fp) { 322 rewind(oscore_seq_num_fp); 323 fprintf(oscore_seq_num_fp, "%lu\n", sender_seq_num); 324 fflush(oscore_seq_num_fp); 325 } 326 return 1; 327} 328 329static int 330setup_context (void) { 331 /* See coap_context(3) */ 332 coap_context_t *context = coap_new_context(NULL); 333 334 if (!context) 335 return 0; 336 337 /* See coap_block(3) */ 338 coap_context_set_block_mode(context, 339 COAP_BLOCK_USE_LIBCOAP | COAP_BLOCK_SINGLE_BODY); 340 341 if (coap_oscore_is_supported()) { 342 coap_str_const_t config = { sizeof (oscore_config), oscore_config }; 343 uint64_t start_seq_num = 0; 344 coap_oscore_conf_t *oscore_conf; 345 346 if (oscore_seq_save_file) { 347 oscore_seq_num_fp = fopen(oscore_seq_save_file, "r+"); 348 if (oscore_seq_num_fp == NULL) { 349 /* Try creating it */ 350 oscore_seq_num_fp = fopen(oscore_seq_save_file, "w+"); 351 if (oscore_seq_num_fp == NULL) { 352 coap_log_err("OSCORE save restart info file error: %s\n", 353 oscore_seq_save_file); 354 return 0; 355 } 356 } 357 fscanf(oscore_seq_num_fp, "%ju", &start_seq_num); 358 } 359 oscore_conf = coap_new_oscore_conf(config, oscore_save_seq_num, 360 NULL, start_seq_num); 361 if (!oscore_conf) { 362 coap_free_context(context); 363 return 0; 364 } 365 coap_context_oscore_server(context, oscore_conf); 366 } 367 return 1; 368} 369 370---- 371 372SEE ALSO 373-------- 374*coap_endpoint_client*(3), *coap_endpoint_server*(3) and *coap-oscore-conf*(5) 375 376FURTHER INFORMATION 377------------------- 378See 379 380"https://rfc-editor.org/rfc/rfc7252[RFC7252: The Constrained Application Protocol (CoAP)]" 381 382"https://rfc-editor.org/rfc/rfc8613[RFC8613: Object Security for Constrained RESTful Environments (OSCORE)]" 383 384for further information. 385 386BUGS 387---- 388Please report bugs on the mailing list for libcoap: 389libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at 390https://github.com/obgm/libcoap/issues 391 392AUTHORS 393------- 394The libcoap project <libcoap-developers@lists.sourceforge.net> 395