• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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