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