libcoap 4.3.5-develop-3f4d08f
Loading...
Searching...
No Matches
coap_oscore.c
Go to the documentation of this file.
1/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
3/*
4 * coap_oscore.c -- Object Security for Constrained RESTful Environments
5 * (OSCORE) support for libcoap
6 *
7 * Copyright (C) 2019-2021 Olaf Bergmann <bergmann@tzi.org>
8 * Copyright (C) 2021-2026 Jon Shallow <supjps-libcoap@jpshallow.com>
9 *
10 * SPDX-License-Identifier: BSD-2-Clause
11 *
12 * This file is part of the CoAP library libcoap. Please see README for terms
13 * of use.
14 */
15
22
23#if COAP_OSCORE_SUPPORT
24#include <ctype.h>
25
26#define AAD_BUF_LEN 200 /* length of aad_buffer */
27
28static oscore_ctx_t *coap_oscore_init(coap_context_t *c_context,
29 coap_oscore_conf_t *oscore_conf);
30
31#if COAP_CLIENT_SUPPORT
32
33int
35 if (oscore_conf) {
36 oscore_ctx_t *osc_ctx;
37
38 if (oscore_conf->recipient_chain == NULL) {
39 coap_log_warn("OSCORE: Recipient ID must be defined for a client\n");
40 coap_delete_oscore_conf(oscore_conf);
41 return 0;
42 }
43 if (oscore_conf->rfc8613_b_2) {
44 /* Need to replace id_context with random value */
45 coap_binary_t *id_context = coap_new_binary(8);
46
47 if (id_context == NULL) {
48 coap_delete_oscore_conf(oscore_conf);
49 return 0;
50 }
52 coap_prng_lkd(id_context->s, id_context->length);
53 oscore_conf->id_context = (coap_bin_const_t *)id_context;
54 session->b_2_step = COAP_OSCORE_B_2_STEP_1;
55 coap_log_oscore("Appendix B.2 client step 1 (Generated ID1)\n");
56 }
57
58 osc_ctx = coap_oscore_init(session->context, oscore_conf);
59 if (osc_ctx == NULL) {
60 return 0;
61 }
62 session->recipient_ctx = osc_ctx->recipient_chain;
63 session->oscore_encryption = 1;
64 }
65 return 1;
66}
67
70 const coap_address_t *local_if,
71 const coap_address_t *server,
72 coap_proto_t proto,
73 coap_oscore_conf_t *oscore_conf) {
74 coap_session_t *session;
75
76 coap_lock_lock(return NULL);
77 session = coap_new_client_session_oscore3_lkd(ctx, local_if, server, proto, oscore_conf, NULL,
78 NULL, NULL);
80 return session;
81}
82
85 const coap_address_t *local_if,
86 const coap_address_t *server,
87 coap_proto_t proto,
88 coap_oscore_conf_t *oscore_conf,
89 void *app_data,
91 coap_str_const_t *ws_host) {
92 coap_session_t *session;
93
94 coap_lock_lock(return NULL);
95 session = coap_new_client_session_oscore3_lkd(ctx, local_if, server, proto, oscore_conf, app_data,
96 callback, ws_host);
98 return session;
99}
100
103 const coap_address_t *local_if,
104 const coap_address_t *server,
105 coap_proto_t proto,
106 coap_oscore_conf_t *oscore_conf,
107 void *app_data,
109 coap_str_const_t *ws_host) {
110 coap_session_t *session =
111 coap_new_client_session3_lkd(ctx, local_if, server, proto, app_data, callback, ws_host);
112
113 if (!session)
114 return NULL;
115
116 if (coap_oscore_initiate(session, oscore_conf) == 0) {
118 return NULL;
119 }
120 return session;
121}
122
125 const coap_address_t *local_if,
126 const coap_address_t *server,
127 coap_proto_t proto,
128 coap_dtls_cpsk_t *psk_data,
129 coap_oscore_conf_t *oscore_conf) {
130 coap_session_t *session;
131
132 coap_lock_lock(return NULL);
133 session = coap_new_client_session_oscore_psk3_lkd(ctx, local_if, server, proto, psk_data,
134 oscore_conf, NULL, NULL, NULL);
136 return session;
137}
138
141 const coap_address_t *local_if,
142 const coap_address_t *server,
143 coap_proto_t proto,
144 coap_dtls_cpsk_t *psk_data,
145 coap_oscore_conf_t *oscore_conf,
146 void *app_data,
148 coap_str_const_t *ws_host) {
149 coap_session_t *session;
150
151 coap_lock_lock(return NULL);
152 session = coap_new_client_session_oscore_psk3_lkd(ctx, local_if, server, proto, psk_data,
153 oscore_conf, app_data, callback, ws_host);
155 return session;
156}
157
160 const coap_address_t *local_if,
161 const coap_address_t *server,
162 coap_proto_t proto,
163 coap_dtls_cpsk_t *psk_data,
164 coap_oscore_conf_t *oscore_conf,
165 void *app_data,
167 coap_str_const_t *ws_host) {
168 coap_session_t *session;
169
171 session = coap_new_client_session_psk3_lkd(ctx, local_if, server, proto, psk_data,
172 app_data, callback, ws_host);
173
174 if (!session)
175 return NULL;
176
177 if (coap_oscore_initiate(session, oscore_conf) == 0) {
179 return NULL;
180 }
181 return session;
182}
183
186 const coap_address_t *local_if,
187 const coap_address_t *server,
188 coap_proto_t proto,
189 coap_dtls_pki_t *pki_data,
190 coap_oscore_conf_t *oscore_conf) {
191 coap_session_t *session;
192
193 coap_lock_lock(return NULL);
194 session = coap_new_client_session_oscore_pki3_lkd(ctx, local_if, server, proto, pki_data,
195 oscore_conf, NULL, NULL, NULL);
197 return session;
198}
199
202 const coap_address_t *local_if,
203 const coap_address_t *server,
204 coap_proto_t proto,
205 coap_dtls_pki_t *pki_data,
206 coap_oscore_conf_t *oscore_conf,
207 void *app_data,
209 coap_str_const_t *ws_host) {
210 coap_session_t *session;
211
212 coap_lock_lock(return NULL);
213 session = coap_new_client_session_oscore_pki3_lkd(ctx, local_if, server, proto, pki_data,
214 oscore_conf, app_data, callback, ws_host);
216 return session;
217}
218
221 const coap_address_t *local_if,
222 const coap_address_t *server,
223 coap_proto_t proto,
224 coap_dtls_pki_t *pki_data,
225 coap_oscore_conf_t *oscore_conf,
226 void *app_data,
228 coap_str_const_t *ws_host) {
229 coap_session_t *session;
230
232 session = coap_new_client_session_pki3_lkd(ctx, local_if, server, proto, pki_data,
233 app_data, callback, ws_host);
234
235 if (!session)
236 return NULL;
237
238 if (coap_oscore_initiate(session, oscore_conf) == 0) {
240 return NULL;
241 }
242 return session;
243}
244#endif /* COAP_CLIENT_SUPPORT */
245#if COAP_SERVER_SUPPORT
246
247COAP_API int
249 coap_oscore_conf_t *oscore_conf) {
250 int ret;
251
252 coap_lock_lock(return 0);
253 ret = coap_context_oscore_server_lkd(context, oscore_conf);
255 return ret;
256}
257
258int
260 coap_oscore_conf_t *oscore_conf) {
261 oscore_ctx_t *osc_ctx;
262
264 osc_ctx = coap_oscore_init(context, oscore_conf);
265 /* osc_ctx already added to context->osc_ctx */
266 if (osc_ctx)
267 return 1;
268 return 0;
269}
270
271#endif /* COAP_SERVER_SUPPORT */
272
273int
275 coap_uri_t uri;
276 coap_opt_iterator_t opt_iter;
277 coap_opt_t *option;
278 uint8_t option_value_buffer[15];
279 coap_optlist_t *optlist_chain = NULL;
280
281 if ((option =
282 coap_check_option(pdu, COAP_OPTION_PROXY_URI, &opt_iter)) == NULL)
283 return 1;
284
285 /* Need to break down into the component parts, but keep data safe */
286 memset(&uri, 0, sizeof(uri));
287
289 coap_opt_length(option),
290 &uri) < 0 || uri.scheme >= COAP_URI_SCHEME_LAST) {
291 coap_log_warn("Proxy URI '%.*s' not decodable\n",
292 coap_opt_length(option),
293 (const char *)coap_opt_value(option));
294 goto error;
295 }
297 goto error;
298
299 if (!coap_insert_option(pdu,
301 uri.host.length,
302 uri.host.s))
303 goto error;
307 coap_encode_var_safe(option_value_buffer,
308 sizeof(option_value_buffer),
309 uri.port & 0xffff),
310 option_value_buffer))
311 goto error;
312 if (uri.path.length) {
313 /* Add in the Uri-Path options */
315 &optlist_chain))
316 goto error;
317 }
318 if (uri.query.length) {
319 /* Add in the Uri-Query options */
321 &optlist_chain))
322 goto error;
323 }
324 if (!coap_add_optlist_pdu(pdu, &optlist_chain))
325 goto error;
326
327 if (!coap_insert_option(pdu,
329 strlen(coap_uri_scheme[uri.scheme].name),
330 (const uint8_t *)coap_uri_scheme[uri.scheme].name))
331 goto error;
332
333 coap_delete_optlist(optlist_chain);
334 return 1;
335
336error:
337 coap_delete_optlist(optlist_chain);
338 return 0;
339}
340
341static void
342dump_cose(cose_encrypt0_t *cose, const char *message) {
343#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_OSCORE
344 (void)cose;
345 (void)message;
346#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_OSCORE */
348 char buffer[30];
349
350 coap_log_oscore("%s COSE information\n", message);
352 cose_get_alg_name(cose->alg, buffer, sizeof(buffer)));
354 oscore_log_hex_value(COAP_LOG_OSCORE, "partial_iv", &cose->partial_iv);
356 oscore_log_hex_value(COAP_LOG_OSCORE, "kid_context", &cose->kid_context);
358 "oscore_option",
359 &cose->oscore_option);
361 oscore_log_hex_value(COAP_LOG_OSCORE, "external_aad", &cose->external_aad);
363 }
364#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_OSCORE */
365}
366
369 coap_pdu_t *pdu,
370 coap_bin_const_t *kid_context,
371 oscore_partial_iv_t send_partial_iv) {
372 coap_pdu_t *ret_pdu;
373
374 coap_lock_lock(return NULL);
375 ret_pdu = coap_oscore_new_pdu_encrypted_lkd(session, pdu, kid_context, send_partial_iv);
377
378 return ret_pdu;
379}
380
381/*
382 * Take current PDU, create a new one approriately separated as per RFC8613
383 * and then encrypt / integrity check the OSCORE data
384 */
387 coap_pdu_t *pdu,
388 coap_bin_const_t *kid_context,
389 oscore_partial_iv_t send_partial_iv) {
390 uint8_t coap_request = COAP_PDU_IS_REQUEST(pdu) || COAP_PDU_IS_PING(pdu);
391 coap_pdu_code_t code =
392 coap_request ? COAP_REQUEST_CODE_POST : COAP_RESPONSE_CODE(204);
393 coap_pdu_t *osc_pdu;
394 coap_pdu_t *plain_pdu = NULL;
395 coap_bin_const_t pdu_token;
396 coap_opt_iterator_t opt_iter;
397 coap_opt_t *option;
398 uint8_t pdu_code = pdu->code;
399 size_t length;
400 const uint8_t *data;
401 uint8_t *ciphertext_buffer = NULL;
402 size_t ciphertext_len = 0;
403 uint8_t aad_buffer[AAD_BUF_LEN];
404 uint8_t nonce_buffer[13];
406 coap_bin_const_t nonce;
407 oscore_recipient_ctx_t *rcp_ctx;
408 oscore_ctx_t *osc_ctx;
409 cose_encrypt0_t cose[1];
410 uint8_t group_flag = 0;
411 int show_pdu = 0;
412 int doing_observe = 0;
413 uint32_t observe_value = 0;
414 oscore_association_t *association = NULL;
415 oscore_sender_ctx_t *snd_ctx;
416 uint8_t external_aad_buffer[200];
417 coap_bin_const_t external_aad;
418 uint8_t oscore_option[48];
419 size_t oscore_option_len;
420
421 /* Check that OSCORE has not already been done */
422 if (coap_check_option(pdu, COAP_OPTION_OSCORE, &opt_iter))
423 return NULL;
424
425 if (coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter))
426 doing_observe = 1;
427
428 coap_log_debug("PDU to encrypt\n");
430 osc_pdu = coap_pdu_init(pdu->type == COAP_MESSAGE_NON &&
431 session->b_2_step != COAP_OSCORE_B_2_NONE ?
432 COAP_MESSAGE_CON : pdu->type,
433 code,
434 pdu->mid,
435 pdu->used_size + coap_oscore_overhead(session, pdu));
436 if (osc_pdu == NULL)
437 return NULL;
438
439 cose_encrypt0_init(cose); /* clears cose memory */
440 pdu_token = coap_pdu_get_token(pdu);
441 if (coap_request) {
442 /*
443 * RFC8613 8.1 Step 1. Protecting the client's request
444 * Get the Sender Context
445 */
446 rcp_ctx = session->recipient_ctx;
447 if (rcp_ctx == NULL)
448 goto error;
449 osc_ctx = rcp_ctx->osc_ctx;
450 assert(osc_ctx);
451 snd_ctx = osc_ctx->sender_context;
452 } else {
453 /*
454 * RFC8613 8.3 Step 1. Protecting the server's response
455 * Get the Sender Context
456 */
457 association = oscore_find_association(session, &pdu_token);
458 if (association == NULL)
459 goto error;
460
461 rcp_ctx = association->recipient_ctx;
462 osc_ctx = rcp_ctx->osc_ctx;
463 snd_ctx = osc_ctx->sender_context;
464 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
465 cose_encrypt0_set_aad(cose, association->aad);
466 }
467
468 cose_encrypt0_set_alg(cose, osc_ctx->aead_alg);
469
470 if (coap_request || doing_observe ||
471 send_partial_iv == OSCORE_SEND_PARTIAL_IV) {
472 uint8_t partial_iv_buffer[8];
473 size_t partial_iv_len;
474 coap_bin_const_t partial_iv;
475 partial_iv_len = coap_encode_var_safe8(partial_iv_buffer,
476 sizeof(partial_iv_buffer),
477 snd_ctx->seq);
478 if (snd_ctx->seq == 0) {
479 /* Need to special case */
480 partial_iv_buffer[0] = '\000';
481 partial_iv_len = 1;
482 }
483 partial_iv.s = partial_iv_buffer;
484 partial_iv.length = partial_iv_len;
485 cose_encrypt0_set_partial_iv(cose, &partial_iv);
486 }
487
488 if (coap_request)
490
491 cose_encrypt0_set_key_id(cose, snd_ctx->sender_id);
492
493 /* nonce (needs to have sender information correctly set up) */
494
495 if (coap_request || doing_observe ||
496 send_partial_iv == OSCORE_SEND_PARTIAL_IV) {
497 /*
498 * 8.1 Step 3 or RFC8613 8.3.1 Step A
499 * Compose the AEAD nonce
500 *
501 * Requires in COSE object as appropriate
502 * key_id (kid) (sender)
503 * partial_iv (sender)
504 * common_iv (already in osc_ctx)
505 */
506 nonce.s = nonce_buffer;
507 nonce.length = 13;
508 oscore_generate_nonce(cose, osc_ctx, nonce_buffer, 13);
509 cose_encrypt0_set_nonce(cose, &nonce);
510 if (!oscore_increment_sender_seq(osc_ctx))
511 goto error;
512 if (osc_ctx->save_seq_num_func) {
513 if (osc_ctx->sender_context->seq > osc_ctx->sender_context->next_seq) {
514 /* Only update at ssn_freq rate */
515 osc_ctx->sender_context->next_seq += osc_ctx->ssn_freq;
516 osc_ctx->save_seq_num_func(osc_ctx->sender_context->next_seq,
517 osc_ctx->save_seq_num_func_param);
518 }
519 }
520 } else {
521 /*
522 * 8.3 Step 3.
523 * Use nonce from request
524 */
525 cose_encrypt0_set_nonce(cose, association->nonce);
526 }
527
528 /* OSCORE_option (needs to be before AAD as included in AAD if group) */
529
530 /* cose is modified for encode option in response message */
531 if (!coap_request) {
532 /* no kid on response */
534 if (!doing_observe && send_partial_iv == OSCORE_SEND_NO_IV)
536 }
537 if (kid_context) {
538 cose_encrypt0_set_kid_context(cose, kid_context);
539 }
540 oscore_option_len =
541 oscore_encode_option_value(oscore_option, sizeof(oscore_option), cose,
542 group_flag,
543 session->b_2_step != COAP_OSCORE_B_2_NONE);
544 if (!coap_request) {
545 /* Reset what was just unset as appropriate for AAD */
547 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
548 }
549 if (kid_context)
551
552 /*
553 * RFC8613 8.1/8.3 Step 2(a) (5.4).
554 * Compose the External AAD and then AAD
555 *
556 * OSCORE_option requires
557 * partial_iv (cose partial_iv)
558 * kid_context (cose kid_context)
559 * key_id (cose key_id)
560 * group_flag
561 *
562 * Non Group requires the following
563 * RFC8613 5.4
564 * oscore_version 1
565 * algorithms [
566 * aead_alg (osc_ctx)
567 * ]
568 * request_kid (request key_id using cose)
569 * request_piv (request partial_iv using cose)
570 * options (none at present)
571 *
572 * Note: No I options at present
573 */
574 if (coap_request || send_partial_iv == OSCORE_SEND_PARTIAL_IV) {
575 /* External AAD */
576 external_aad.s = external_aad_buffer;
577 external_aad.length = oscore_prepare_e_aad(osc_ctx,
578 cose,
579 NULL,
580 0,
581 NULL,
582 external_aad_buffer,
583 sizeof(external_aad_buffer));
584 cose_encrypt0_set_external_aad(cose, &external_aad);
585
586 /* AAD */
587 aad.s = aad_buffer;
588 aad.length = oscore_prepare_aad(external_aad_buffer,
589 external_aad.length,
590 aad_buffer,
591 sizeof(aad_buffer));
592 assert(aad.length < AAD_BUF_LEN);
593 cose_encrypt0_set_aad(cose, &aad);
594 }
595
596 /*
597 * RFC8613 8.1/8.3 Step 2(b) (5.3).
598 *
599 * Set up temp plaintext pdu, the data including token, options and
600 * optional payload will get encrypted as COSE ciphertext.
601 */
602 plain_pdu = coap_pdu_init(pdu->type,
603 pdu->code,
604 pdu->mid,
605 pdu->used_size + 1 /* pseudo-token with actual code */);
606 if (plain_pdu == NULL)
607 goto error;
608
609 coap_add_token(osc_pdu, pdu_token.length, pdu_token.s);
610
611 /* First byte of plain is real CoAP code. Pretend it is token */
612 coap_add_token(plain_pdu, 1, &pdu_code);
613
614 /* Copy across the Outer/Inner Options to respective PDUs */
616 while ((option = coap_option_next(&opt_iter))) {
617 switch (opt_iter.number) {
622 /* Outer only */
623 if (!coap_insert_option(osc_pdu,
624 opt_iter.number,
625 coap_opt_length(option),
626 coap_opt_value(option)))
627 goto error;
628 break;
630 /* Make as Outer option as-is */
631 if (!coap_insert_option(osc_pdu,
632 opt_iter.number,
633 coap_opt_length(option),
634 coap_opt_value(option)))
635 goto error;
636 if (coap_request) {
637 /* Make as Inner option (unchanged) */
638 if (!coap_insert_option(plain_pdu,
639 opt_iter.number,
640 coap_opt_length(option),
641 coap_opt_value(option)))
642 goto error;
643 osc_pdu->code = COAP_REQUEST_CODE_FETCH;
644 } else {
645 /* Make as Inner option but empty */
646 if (!coap_insert_option(plain_pdu, opt_iter.number, 0, NULL))
647 goto error;
648 osc_pdu->code = COAP_RESPONSE_CODE(205);
649 }
650 show_pdu = 1;
651 doing_observe = 1;
652 observe_value = coap_decode_var_bytes(coap_opt_value(option),
653 coap_opt_length(option));
654 break;
656 /*
657 * Should have already been caught by doing
658 * coap_rebuild_pdu_for_proxy() before calling
659 * coap_oscore_new_pdu_encrypted_lkd()
660 */
661 assert(0);
662 break;
663 default:
664 /* Make as Inner option */
665 if (!coap_insert_option(plain_pdu,
666 opt_iter.number,
667 coap_opt_length(option),
668 coap_opt_value(option)))
669 goto error;
670 break;
671 }
672 }
673 /* Add in data to plain */
674 if (coap_get_data(pdu, &length, &data)) {
675 if (!coap_add_data(plain_pdu, length, data))
676 goto error;
677 }
678 if (show_pdu) {
679 coap_log_oscore("OSCORE payload\n");
680 coap_show_pdu(COAP_LOG_OSCORE, plain_pdu);
681 }
682
683 /*
684 * 8.1/8.3 Step 4.
685 * Encrypt the COSE object.
686 *
687 * Requires in COSE object as appropriate
688 * alg (already set)
689 * key (sender key)
690 * nonce (already set)
691 * aad (already set)
692 * plaintext
693 */
694 cose_encrypt0_set_key(cose, snd_ctx->sender_key);
695 cose_encrypt0_set_plaintext(cose, plain_pdu->token, plain_pdu->used_size);
696 dump_cose(cose, "Pre encrypt");
697 ciphertext_buffer =
698 coap_malloc_type(COAP_OSCORE_BUF, OSCORE_CRYPTO_BUFFER_SIZE);
699 if (ciphertext_buffer == NULL)
700 goto error;
701 ciphertext_len = cose_encrypt0_encrypt(cose,
702 ciphertext_buffer,
703 plain_pdu->used_size + AES_CCM_TAG);
704 if ((int)ciphertext_len <= 0) {
705 coap_log_warn("OSCORE: Encryption Failure, result code: %d \n",
706 (int)ciphertext_len);
707 goto error;
708 }
709 assert(ciphertext_len < OSCORE_CRYPTO_BUFFER_SIZE);
710
711 /* Add in OSCORE option (previously computed) */
712 if (!coap_insert_option(osc_pdu,
714 oscore_option_len,
715 oscore_option))
716 goto error;
717
718 /* Add now encrypted payload */
719 if (!coap_add_data(osc_pdu, ciphertext_len, ciphertext_buffer))
720 goto error;
721
722 coap_free_type(COAP_OSCORE_BUF, ciphertext_buffer);
723 ciphertext_buffer = NULL;
724
725 coap_delete_pdu_lkd(plain_pdu);
726 plain_pdu = NULL;
727
728 if (association && association->is_observe == 0)
729 oscore_delete_association(session, association);
730 association = NULL;
731
732 if (!(session->block_mode & COAP_BLOCK_CACHE_RESPONSE)) {
733 /*
734 * If this is a response ACK with data, make it a separate response
735 * by sending an Empty ACK and changing osc_pdu's MID and type. This
736 * then allows lost response ACK (now CON) with data to be recovered.
737 */
738 if (coap_request == 0 && osc_pdu->type == COAP_MESSAGE_ACK &&
739 COAP_RESPONSE_CLASS(pdu->code) == 2 &&
740 COAP_PROTO_NOT_RELIABLE(session->proto)) {
742 0,
743 osc_pdu->mid,
744 0);
745 if (empty) {
746 if (coap_send_internal(session, empty, NULL) != COAP_INVALID_MID) {
747 osc_pdu->mid = coap_new_message_id_lkd(session);
748 osc_pdu->type = COAP_MESSAGE_CON;
749 }
750 }
751 }
752 }
753
754 if (!coap_pdu_encode_header(osc_pdu, session->proto)) {
755 goto error;
756 }
757
758 /*
759 * Set up an association for handling a response if this is a request
760 */
761 if (coap_request) {
762 association = oscore_find_association(session, &pdu_token);
763 if (association) {
764 /* Refresh the association */
765 coap_delete_bin_const(association->nonce);
766 association->nonce =
767 coap_new_bin_const(cose->nonce.s, cose->nonce.length);
768 if (association->nonce == NULL)
769 goto error;
770 coap_delete_bin_const(association->aad);
771 association->aad = coap_new_bin_const(cose->aad.s, cose->aad.length);
772 if (association->aad == NULL)
773 goto error;
774 if (doing_observe && observe_value == 1) {
776 association->obs_partial_iv = association->partial_iv;
777 } else {
778 coap_delete_bin_const(association->partial_iv);
779 }
780 association->partial_iv =
782 if (association->partial_iv == NULL)
783 goto error;
784 association->recipient_ctx = rcp_ctx;
785 coap_delete_pdu_lkd(association->sent_pdu);
786 if (session->b_2_step != COAP_OSCORE_B_2_NONE || association->just_set_up) {
787 size_t size;
788
789 association->sent_pdu = coap_pdu_duplicate_lkd(pdu, session,
790 pdu_token.length,
791 pdu_token.s, NULL);
792 if (association->sent_pdu == NULL)
793 goto error;
794 if (coap_get_data(pdu, &size, &data)) {
795 coap_add_data(association->sent_pdu, size, data);
796 }
797 association->just_set_up = 0;
798 } else {
799 association->sent_pdu = NULL;
800 }
801 } else if (!oscore_new_association(session,
802 pdu,
803 &pdu_token,
804 rcp_ctx,
805 &cose->aad,
806 &cose->nonce,
807 &cose->partial_iv,
808 doing_observe)) {
809 goto error;
810 }
811 }
812 return osc_pdu;
813
814error:
815 if (ciphertext_buffer)
816 coap_free_type(COAP_OSCORE_BUF, ciphertext_buffer);
817 coap_delete_pdu_lkd(osc_pdu);
818 coap_delete_pdu_lkd(plain_pdu);
819 return NULL;
820}
821
822static void
823build_and_send_error_pdu(coap_session_t *session,
824 coap_pdu_t *rcvd,
825 coap_pdu_code_t code,
826 const char *diagnostic,
827 uint8_t *echo_data,
828 coap_bin_const_t *kid_context,
829 int encrypt_oscore) {
830 coap_pdu_t *err_pdu = NULL;
831 coap_bin_const_t token;
832 int oscore_encryption = session->oscore_encryption;
833 unsigned char buf[4];
834
835 token = coap_pdu_get_token(rcvd);
838 code,
839 rcvd->mid,
840 token.length + 2 + 8 +
841 (diagnostic ? strlen(diagnostic) : 0));
842 if (!err_pdu)
843 return;
844 coap_add_token(err_pdu, token.length, token.s);
845 if (echo_data) {
846 coap_add_option_internal(err_pdu, COAP_OPTION_ECHO, 8, echo_data);
847 } else if (kid_context == NULL) {
850 coap_encode_var_safe(buf, sizeof(buf), 0),
851 buf);
852 }
853 if (diagnostic)
854 coap_add_data(err_pdu, strlen(diagnostic), (const uint8_t *)diagnostic);
855 session->oscore_encryption = encrypt_oscore;
856
857 if ((echo_data || kid_context) && encrypt_oscore) {
858 coap_pdu_t *osc_pdu;
859
860 osc_pdu =
861 coap_oscore_new_pdu_encrypted_lkd(session, err_pdu, kid_context,
862 echo_data ? 1 : 0);
863 if (!osc_pdu)
864 goto fail_resp;
865 session->oscore_encryption = 0;
866 coap_send_internal(session, osc_pdu, NULL);
867 coap_delete_pdu_lkd(err_pdu);
868 err_pdu = NULL;
869 } else {
870 coap_send_internal(session, err_pdu, NULL);
871 err_pdu = NULL;
872 }
873fail_resp:
874 session->oscore_encryption = oscore_encryption;
875 coap_delete_pdu_lkd(err_pdu);
876 return;
877}
878
879/* pdu contains incoming message with encrypted COSE ciphertext payload
880 * function returns decrypted message
881 * and verifies signature, if present
882 * returns NULL when decryption,verification fails
883 */
886 coap_pdu_t *pdu) {
887 coap_pdu_t *decrypt_pdu = NULL;
888 coap_pdu_t *plain_pdu = NULL;
889 const uint8_t *osc_value; /* value of OSCORE option */
890 uint8_t osc_size; /* size of OSCORE OPTION */
891 coap_opt_iterator_t opt_iter;
892 coap_opt_t *opt = NULL;
893 cose_encrypt0_t cose[1];
894 oscore_ctx_t *osc_ctx = NULL;
895 uint8_t aad_buffer[AAD_BUF_LEN];
896 uint8_t nonce_buffer[13];
898 coap_bin_const_t nonce;
899 int pltxt_size = 0;
900 int got_resp_piv = 0;
901 int doing_resp_observe = 0;
902 uint8_t coap_request = COAP_PDU_IS_REQUEST(pdu);
903 coap_bin_const_t pdu_token;
904 uint8_t *st_encrypt;
905 size_t encrypt_len;
906 size_t tag_len;
907 oscore_recipient_ctx_t *rcp_ctx = NULL;
908 oscore_association_t *association = NULL;
909 uint8_t external_aad_buffer[100];
910 coap_bin_const_t external_aad;
911 oscore_sender_ctx_t *snd_ctx = NULL;
912#if COAP_CLIENT_SUPPORT
913 coap_pdu_t *sent_pdu = NULL;
914#endif /* COAP_CLIENT_SUPPORT */
915
916 opt = coap_check_option(pdu, COAP_OPTION_OSCORE, &opt_iter);
917 assert(opt);
918 if (opt == NULL)
919 return NULL;
920
921 if (session->context->p_osc_ctx == NULL) {
922 coap_log_warn("OSCORE: Not enabled\n");
923 if (!coap_request)
926 session);
927 return NULL;
928 }
929
930 if (pdu->data == NULL) {
931 coap_log_warn("OSCORE: No protected payload\n");
932 if (!coap_request)
935 session);
936 return NULL;
937 }
938
939 osc_size = coap_opt_length(opt);
940 osc_value = coap_opt_value(opt);
941
942 cose_encrypt0_init(cose); /* clear cose memory */
943
944 /* PDU code will be filled in after decryption */
945 decrypt_pdu =
946 coap_pdu_init(pdu->type, 0, pdu->mid, pdu->used_size);
947 if (decrypt_pdu == NULL) {
948 if (!coap_request)
951 session);
952 goto error;
953 }
954
955 /* Copy across the Token */
956 pdu_token = coap_pdu_get_token(pdu);
957 coap_add_token(decrypt_pdu, pdu_token.length, pdu_token.s);
958
959 /*
960 * 8.2/8.4 Step 1.
961 * Copy outer options across, except E and OSCORE options
962 */
964 while ((opt = coap_option_next(&opt_iter))) {
965 switch (opt_iter.number) {
966 /* 'E' options skipped */
968 case COAP_OPTION_ETAG:
983 case COAP_OPTION_ECHO:
984 case COAP_OPTION_RTAG:
985 /* OSCORE does not get copied across */
987 break;
988 default:
989 if (!coap_add_option_internal(decrypt_pdu,
990 opt_iter.number,
991 coap_opt_length(opt),
992 coap_opt_value(opt))) {
993 if (!coap_request)
996 session);
997 goto error;
998 }
999 break;
1000 }
1001 }
1002
1003 if (coap_request) {
1004 uint64_t incoming_seq;
1005 /*
1006 * 8.2 Step 2
1007 * Decompress COSE object
1008 * Get Recipient Context based on kid and optional kid_context
1009 */
1010 if (oscore_decode_option_value(osc_value, osc_size, cose) == 0) {
1011 coap_log_warn("OSCORE: OSCORE Option cannot be decoded.\n");
1012 build_and_send_error_pdu(session,
1013 pdu,
1014 COAP_RESPONSE_CODE(402),
1015 "Failed to decode COSE",
1016 NULL,
1017 NULL,
1018 0);
1019 goto error_no_ack;
1020 }
1021 osc_ctx = oscore_find_context(session,
1022 cose->key_id,
1023 &cose->kid_context,
1024 NULL,
1025 &rcp_ctx);
1026 if (!osc_ctx) {
1027 if (cose->kid_context.length > 0) {
1028 const uint8_t *ptr;
1029 size_t length;
1030 /* Appendix B.2 protocol check - Is the recipient key_id known */
1031 osc_ctx = oscore_find_context(session,
1032 cose->key_id,
1033 NULL,
1034 session->oscore_r2 != 0 ? (uint8_t *)&session->oscore_r2 : NULL,
1035 &rcp_ctx);
1036 ptr = cose->kid_context.s;
1037 length = cose->kid_context.length;
1038 if (ptr && osc_ctx && osc_ctx->rfc8613_b_2) {
1039 /* Processing Appendix B.2 protocol */
1040 /* Need to CBOR unwrap kid_context */
1041 coap_bin_const_t kid_context;
1042
1043 kid_context.length = oscore_cbor_get_element_size(&ptr, &length);
1044 if (kid_context.length > length)
1045 goto error;
1046 /* This has to fit into an OSCORE option max 255.
1047 * Initial byte, kid_context size, partial IV size and kid size have to be there
1048 */
1049 if (kid_context.length >= 255 - 1 - 1 - cose->partial_iv.length - cose->key_id.length)
1050 goto error;
1051 kid_context.s = ptr;
1052 cose_encrypt0_set_kid_context(cose, (coap_bin_const_t *)&kid_context);
1053
1054 if (session->oscore_r2 != 0) {
1055 /* B.2 step 4 */
1057 cose->kid_context.length);
1058
1059 if (kc == NULL)
1060 goto error;
1061
1062 session->b_2_step = COAP_OSCORE_B_2_STEP_4;
1063 coap_log_oscore("Appendix B.2 server step 4 (R2 || R3)\n");
1064 oscore_update_ctx(osc_ctx, kc);
1065 } else {
1066 session->b_2_step = COAP_OSCORE_B_2_STEP_2;
1067 coap_log_oscore("Appendix B.2 server step 2 (ID1)\n");
1068 osc_ctx = oscore_duplicate_ctx(session->context,
1069 osc_ctx,
1070 osc_ctx->sender_context->sender_id,
1071 &cose->key_id,
1072 &cose->kid_context);
1073 if (osc_ctx == NULL)
1074 goto error;
1075 /*
1076 * Complete the Verify (B.2 step 2)
1077 * before sending back the response
1078 */
1079 rcp_ctx = osc_ctx->recipient_chain;
1080 }
1081 } else {
1082 osc_ctx = NULL;
1083 }
1084 }
1085 } else if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
1086 session->b_2_step = COAP_OSCORE_B_2_NONE;
1087 coap_log_oscore("Appendix B.2 server finished\n");
1088 }
1089 if (!osc_ctx) {
1090 coap_log_err("OSCORE: Security Context not found\n");
1091 oscore_log_hex_value(COAP_LOG_OSCORE, "key_id", &cose->key_id);
1092 oscore_log_hex_value(COAP_LOG_OSCORE, "kid_context", &cose->kid_context);
1093 build_and_send_error_pdu(session,
1094 pdu,
1095 COAP_RESPONSE_CODE(401),
1096 "Security context not found",
1097 NULL,
1098 NULL,
1099 0);
1100 goto error_no_ack;
1101 }
1102 /* to be used for encryption of returned response later */
1103 session->recipient_ctx = rcp_ctx;
1104 snd_ctx = osc_ctx->sender_context;
1105
1106 /*
1107 * 8.2 Step 3.
1108 * Verify Partial IV is not duplicated.
1109 *
1110 * Requires in COSE object as appropriate
1111 * partial_iv (as received)
1112 */
1113 if (rcp_ctx->initial_state == 0 &&
1114 !oscore_validate_sender_seq(rcp_ctx, cose)) {
1115 coap_log_warn("OSCORE: Replayed or old message\n");
1116 build_and_send_error_pdu(session,
1117 pdu,
1118 COAP_RESPONSE_CODE(401),
1119 "Replay detected",
1120 NULL,
1121 NULL,
1122 0);
1123 goto error_no_ack;
1124 }
1125 if (rcp_ctx->initial_state == 1) {
1126 incoming_seq =
1128 rcp_ctx->last_seq = incoming_seq;
1129 }
1130 } else { /* !coap_request */
1131 /*
1132 * 8.4 Step 2
1133 * Decompress COSE object
1134 * Get Recipient Context based on token
1135 */
1136 if (oscore_decode_option_value(osc_value, osc_size, cose) == 0) {
1137 coap_log_warn("OSCORE: OSCORE Option cannot be decoded.\n");
1140 session);
1141 goto error;
1142 }
1143 got_resp_piv = cose->partial_iv.length ? 1 : 0;
1144
1145 association = oscore_find_association(session, &pdu_token);
1146 if (association) {
1147 rcp_ctx = association->recipient_ctx;
1148 osc_ctx = rcp_ctx->osc_ctx;
1149 snd_ctx = osc_ctx->sender_context;
1150#if COAP_CLIENT_SUPPORT
1151 sent_pdu = association->sent_pdu;
1152 if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
1153 const uint8_t *ptr = cose->kid_context.s;
1154 size_t length = cose->kid_context.length;
1155
1156 if (ptr) {
1157 /* Need to CBOR unwrap kid_context */
1158 coap_bin_const_t kid_context;
1159
1160 kid_context.length = oscore_cbor_get_element_size(&ptr, &length);
1161 if (kid_context.length > length)
1162 goto error;
1163 /* This has to fit into an OSCORE option max 255.
1164 * Initial byte, kid_context size, partial IV size and kid size have to be there
1165 */
1166 if (kid_context.length >= 255 - 1 - 1 - cose->partial_iv.length - cose->key_id.length)
1167 goto error;
1168 kid_context.s = ptr;
1169 cose_encrypt0_set_kid_context(cose, &kid_context);
1170 }
1171 if (ptr && !coap_binary_equal(osc_ctx->id_context, &cose->kid_context)) {
1172 /* If Appendix B.2 step 3 is in operation */
1173 /* Need to update Security Context with new (R2 || ID1) ID Context */
1175 osc_ctx->id_context->length);
1176
1177 if (kc == NULL) {
1180 session);
1181 goto error;
1182 }
1183
1184 memcpy(kc->s, cose->kid_context.s, cose->kid_context.length);
1185 memcpy(&kc->s[cose->kid_context.length],
1186 osc_ctx->id_context->s,
1187 osc_ctx->id_context->length);
1188
1189 session->b_2_step = COAP_OSCORE_B_2_STEP_3;
1190 coap_log_oscore("Appendix B.2 client step 3 (R2 || ID1)\n");
1191 oscore_update_ctx(osc_ctx, (coap_bin_const_t *)kc);
1192 } else {
1193 session->b_2_step = COAP_OSCORE_B_2_STEP_5;
1194 coap_log_oscore("Appendix B.2 client step 5 (R2 || R3)\n");
1195 }
1196 }
1197#endif /* COAP_CLIENT_SUPPORT */
1198 } else {
1199 coap_log_crit("OSCORE: Security Context association not found\n");
1202 session);
1203 goto error;
1204 }
1205 }
1206
1207 cose_encrypt0_set_alg(cose, osc_ctx->aead_alg);
1208
1209 if (coap_request) {
1210 /*
1211 * RFC8613 8.2 Step 4.
1212 * Compose the External AAD and then AAD
1213 *
1214 * OSCORE_option requires
1215 * partial_iv (cose partial_iv)
1216 * kid_context (cose kid_context)
1217 * key_id (cose key_id)
1218 * group_flag
1219 *
1220 * Non Group requires the following
1221 * RFC8613 5.4
1222 * oscore_version 1
1223 * algorithms [
1224 * aead_alg (osc_ctx)
1225 * ]
1226 * request_kid (request key_id using cose)
1227 * request_piv (request partial_iv using cose)
1228 * options (none at present)
1229 *
1230 * Note: No I options at present
1231 */
1232
1233 /* External AAD */
1234 external_aad.s = external_aad_buffer;
1235 external_aad.length = oscore_prepare_e_aad(osc_ctx,
1236 cose,
1237 osc_value,
1238 osc_size,
1239 NULL,
1240 external_aad_buffer,
1241 sizeof(external_aad_buffer));
1242 cose_encrypt0_set_external_aad(cose, &external_aad);
1243
1244 /* AAD */
1245 aad.s = aad_buffer;
1246 aad.length = oscore_prepare_aad(external_aad_buffer,
1247 external_aad.length,
1248 aad_buffer,
1249 sizeof(aad_buffer));
1250 assert(aad.length < AAD_BUF_LEN);
1251 cose_encrypt0_set_aad(cose, &aad);
1252
1253 /*
1254 * RFC8613 8.2 Step 5.
1255 * Compute the AEAD nonce.
1256 *
1257 * Requires in COSE object as appropriate
1258 * key_id (kid) (Recipient ID)
1259 * partial_iv (as received in request)
1260 * common_iv (already in osc_ctx)
1261 */
1262 nonce.s = nonce_buffer;
1263 nonce.length = 13;
1264 oscore_generate_nonce(cose, osc_ctx, nonce_buffer, 13);
1265 cose_encrypt0_set_nonce(cose, &nonce);
1266 /*
1267 * Set up an association for use in the response
1268 */
1269 association = oscore_find_association(session, &pdu_token);
1270 if (association) {
1271 /* Refresh the association */
1272 coap_delete_bin_const(association->nonce);
1273 association->nonce =
1274 coap_new_bin_const(cose->nonce.s, cose->nonce.length);
1275 if (association->nonce == NULL)
1276 goto error;
1277 coap_delete_bin_const(association->partial_iv);
1278 association->partial_iv =
1280 if (association->partial_iv == NULL)
1281 goto error;
1282 coap_delete_bin_const(association->aad);
1283 association->aad = coap_new_bin_const(cose->aad.s, cose->aad.length);
1284 if (association->aad == NULL)
1285 goto error;
1286 association->recipient_ctx = rcp_ctx;
1287 /* So association is not released when handling decrypt */
1288 association = NULL;
1289 } else if (!oscore_new_association(session,
1290 NULL,
1291 &pdu_token,
1292 rcp_ctx,
1293 &cose->aad,
1294 &cose->nonce,
1295 &cose->partial_iv,
1296 0)) {
1297 goto error;
1298 }
1299 /* So association is not released when handling decrypt */
1300 association = NULL;
1301 } else { /* ! coap_request */
1302 /* Need to do nonce before AAD because of different partial_iv */
1303 /*
1304 * 8.4 Step 4.
1305 * Compose the AEAD nonce.
1306 */
1307 cose_encrypt0_set_key_id(cose, rcp_ctx->recipient_id);
1308 if (cose->partial_iv.length == 0) {
1309 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
1310 cose_encrypt0_set_nonce(cose, association->nonce);
1311 } else {
1312 uint64_t last_seq;
1313
1314 if (rcp_ctx->initial_state == 0 &&
1315 !oscore_validate_sender_seq(rcp_ctx, cose)) {
1316 coap_log_warn("OSCORE: Replayed or old message\n");
1317 goto error;
1318 }
1319 last_seq =
1321 if (rcp_ctx->last_seq>= OSCORE_SEQ_MAX) {
1322 coap_log_warn("OSCORE Replay protection, SEQ larger than SEQ_MAX.\n");
1323 goto error;
1324 }
1325 if (last_seq > rcp_ctx->last_seq)
1326 rcp_ctx->last_seq = last_seq;
1327 /*
1328 * Requires in COSE object as appropriate
1329 * kid (set above)
1330 * partial_iv (as received)
1331 * common_iv (already in osc_ctx)
1332 */
1333 oscore_generate_nonce(cose, osc_ctx, nonce_buffer, 13);
1334 nonce.s = nonce_buffer;
1335 nonce.length = 13;
1336 cose_encrypt0_set_nonce(cose, &nonce);
1337 }
1338#ifdef OSCORE_EXTRA_DEBUG
1339 dump_cose(cose, "!req post set nonce");
1340#endif /* OSCORE_EXTRA_DEBUG */
1341 /*
1342 * 8.4 Step 3.
1343 * Compose the External AAD and then AAD
1344 *
1345 * OSCORE_option requires
1346 * partial_iv (cose partial_iv)
1347 * kid_context (cose kid_context)
1348 * key_id (cose key_id)
1349 * group_flag
1350 *
1351 * Non Group requires the following
1352 * RFC8613 5.4
1353 * oscore_version 1
1354 * algorithms [
1355 * aead_alg (osc_ctx)
1356 * ]
1357 * request_kid (request key_id using cose)
1358 * request_piv (request partial_iv using cose)
1359 * options (none at present)
1360 *
1361 * Note: No I options at present
1362 */
1363
1364 /* External AAD */
1365 cose_encrypt0_set_key_id(cose, snd_ctx->sender_id);
1366 if (association->is_observe && association->obs_partial_iv && got_resp_piv) {
1367 cose_encrypt0_set_partial_iv(cose, association->obs_partial_iv);
1368 } else {
1369 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
1370 }
1371#ifdef OSCORE_EXTRA_DEBUG
1372 dump_cose(cose, "!req pre aad");
1373#endif /* OSCORE_EXTRA_DEBUG */
1374 external_aad.s = external_aad_buffer;
1375 external_aad.length = oscore_prepare_e_aad(osc_ctx,
1376 cose,
1377 NULL,
1378 0,
1379 NULL,
1380 external_aad_buffer,
1381 sizeof(external_aad_buffer));
1382 cose_encrypt0_set_external_aad(cose, &external_aad);
1383
1384 /* AAD */
1385 aad.s = aad_buffer;
1386 aad.length = oscore_prepare_aad(external_aad_buffer,
1387 external_aad.length,
1388 aad_buffer,
1389 sizeof(aad_buffer));
1390 assert(aad.length < AAD_BUF_LEN);
1391 cose_encrypt0_set_aad(cose, &aad);
1392#ifdef OSCORE_EXTRA_DEBUG
1393 dump_cose(cose, "!req post set aad");
1394#endif /* OSCORE_EXTRA_DEBUG */
1395 }
1396
1397 /*
1398 * 8.2 Step 6 / 8.4 Step 5.
1399 * Decrypt the COSE object.
1400 *
1401 * Requires in COSE object as appropriate
1402 * alg (already set)
1403 * key
1404 * nonce (already set)
1405 * aad (already set)
1406 * ciphertext
1407 */
1408 st_encrypt = pdu->data;
1409 encrypt_len = pdu->used_size - (pdu->data - pdu->token);
1410 if (encrypt_len <= 0) {
1411 coap_log_warn("OSCORE: No protected payload\n");
1412 if (!coap_request)
1415 session);
1416 goto error;
1417 }
1418 cose_encrypt0_set_key(cose, rcp_ctx->recipient_key);
1419 cose_encrypt0_set_ciphertext(cose, st_encrypt, encrypt_len);
1420
1421 tag_len = cose_tag_len(cose->alg);
1422 /* Decrypt into plain_pdu, so code (token), options and data are in place */
1423 plain_pdu = coap_pdu_init(0, 0, 0, encrypt_len /* - tag_len */);
1424 if (plain_pdu == NULL) {
1425 if (!coap_request)
1428 session);
1429 goto error;
1430 }
1431
1432 /* need the tag_len on the end for TinyDTLS to do its work - yuk */
1433 if (!coap_pdu_resize(plain_pdu, encrypt_len /* - tag_len */)) {
1434 if (!coap_request)
1437 session);
1438 goto error;
1439 }
1440
1441 /* Account for 1 byte 'code' used as token */
1442 plain_pdu->e_token_length = 1;
1443 plain_pdu->actual_token.length = 1;
1444 /* Account for the decrypted data */
1445 plain_pdu->used_size = encrypt_len - tag_len;
1446
1447 dump_cose(cose, "Pre decrypt");
1448 pltxt_size =
1449 cose_encrypt0_decrypt(cose, plain_pdu->token, encrypt_len - tag_len);
1450 if (pltxt_size <= 0) {
1451 coap_log_warn("OSCORE: Decryption Failure, result code: %d \n",
1452 (int)pltxt_size);
1453 if (coap_request) {
1454 build_and_send_error_pdu(session,
1455 pdu,
1456 COAP_RESPONSE_CODE(400),
1457 "Decryption failed",
1458 NULL,
1459 NULL,
1460 0);
1461 oscore_roll_back_seq(rcp_ctx);
1462 goto error_no_ack;
1463 } else {
1466 session);
1467 }
1468 goto error;
1469 }
1470
1471 assert((size_t)pltxt_size < pdu->alloc_size + pdu->max_hdr_size);
1472
1473 /* Appendix B.2 Trap */
1474 if (session->b_2_step == COAP_OSCORE_B_2_STEP_2) {
1475 /* Need to update Security Context with new (R2 || ID1) ID Context */
1476 coap_binary_t *kc =
1477 coap_new_binary(sizeof(session->oscore_r2) + cose->kid_context.length);
1478 coap_bin_const_t oscore_r2;
1479
1480 if (kc == NULL) {
1481 if (!coap_request)
1484 session);
1485 goto error;
1486 }
1487
1488 coap_prng_lkd(&session->oscore_r2, sizeof(session->oscore_r2));
1489 memcpy(kc->s, &session->oscore_r2, sizeof(session->oscore_r2));
1490 memcpy(&kc->s[sizeof(session->oscore_r2)],
1491 cose->kid_context.s,
1492 cose->kid_context.length);
1493
1494 coap_log_oscore("Appendix B.2 server step 2 (R2 || ID1)\n");
1495 oscore_update_ctx(osc_ctx, (coap_bin_const_t *)kc);
1496
1497 oscore_r2.length = sizeof(session->oscore_r2);
1498 oscore_r2.s = (const uint8_t *)&session->oscore_r2;
1499 coap_log_oscore("Appendix B.2 server step 2 plain response\n");
1500 build_and_send_error_pdu(session,
1501 pdu,
1502 COAP_RESPONSE_CODE(401),
1503 NULL,
1504 NULL,
1505 &oscore_r2,
1506 1);
1507 goto error_no_ack;
1508 }
1509#if COAP_CLIENT_SUPPORT
1510 if (session->b_2_step == COAP_OSCORE_B_2_STEP_3) {
1511 coap_log_oscore("Appendix B.2 client step 3 (R2 || R3)\n");
1512 coap_pdu_encode_header(plain_pdu, session->proto);
1513 plain_pdu->actual_token.s = plain_pdu->token;
1514 plain_pdu->code = plain_pdu->token[0];
1515 if (plain_pdu->code != COAP_RESPONSE_CODE(401)) {
1516 coap_log_warn("OSCORE Appendix B.2: Expected 4.01 response\n");
1517 }
1518 /* Skip the options */
1519 coap_option_iterator_init(plain_pdu, &opt_iter, COAP_OPT_ALL);
1520 while (coap_option_next(&opt_iter)) {
1521 }
1522 if (opt_iter.length > 0 && opt_iter.next_option &&
1523 opt_iter.next_option[0] == COAP_PAYLOAD_START) {
1524 plain_pdu->data = &opt_iter.next_option[1];
1525 }
1526 coap_log_oscore("Inner Response PDU (plaintext)\n");
1527 coap_show_pdu(COAP_LOG_OSCORE, plain_pdu);
1528 /*
1529 * Need to update Security Context with new (R2 || R3) ID Context
1530 * and retransmit the request
1531 */
1533
1534 if (kc == NULL) {
1535 if (!coap_request)
1538 session);
1539 goto error;
1540 }
1541 memcpy(kc->s, cose->kid_context.s, cose->kid_context.length);
1542 coap_prng_lkd(&kc->s[cose->kid_context.length], 8);
1543
1544 oscore_update_ctx(osc_ctx, (coap_bin_const_t *)kc);
1545
1547 session,
1548 &pdu->actual_token);
1549 if (session->con_active)
1550 session->con_active--;
1551 coap_send_ack_lkd(session, pdu);
1552 if (sent_pdu) {
1553 coap_log_oscore("Appendix B.2 retransmit pdu\n");
1554 if (coap_retransmit_oscore_pdu(session, sent_pdu, NULL) ==
1556 goto error_no_ack;
1557 }
1558 goto error_no_ack;
1559 }
1560#endif /* COAP_CLIENT_SUPPORT */
1561
1562#if COAP_SERVER_SUPPORT
1563 /* Appendix B.1.2 request Trap */
1564 if (coap_request && osc_ctx->rfc8613_b_1_2) {
1565 if (rcp_ctx->initial_state == 1) {
1566 opt = coap_check_option(plain_pdu, COAP_OPTION_ECHO, &opt_iter);
1567 if (opt) {
1568 /* Verify Client is genuine */
1569 if (coap_opt_length(opt) == 8 &&
1570 memcmp(coap_opt_value(opt), rcp_ctx->echo_value, 8) == 0) {
1571 if (!oscore_validate_sender_seq(rcp_ctx, cose)) {
1572 coap_log_warn("OSCORE: Replayed or old message\n");
1573 build_and_send_error_pdu(session,
1574 pdu,
1575 COAP_RESPONSE_CODE(401),
1576 "Replay detected",
1577 NULL,
1578 NULL,
1579 0);
1580 goto error_no_ack;
1581 }
1582 } else
1583 goto error;
1584 } else {
1585 /* RFC 8163 Appendix B.1.2 */
1586 if (session->b_2_step == COAP_OSCORE_B_2_STEP_4) {
1587 session->b_2_step = COAP_OSCORE_B_2_NONE;
1588 coap_log_oscore("Appendix B.2 server finished\n");
1589 }
1590 coap_prng_lkd(rcp_ctx->echo_value, sizeof(rcp_ctx->echo_value));
1591 coap_log_oscore("Appendix B.1.2 server plain response\n");
1592 build_and_send_error_pdu(session,
1593 pdu,
1594 COAP_RESPONSE_CODE(401),
1595 NULL,
1596 rcp_ctx->echo_value,
1597 NULL,
1598 1);
1599 goto error_no_ack;
1600 }
1601 }
1602 }
1603#endif /* COAP_SERVER_SUPPORT */
1604
1605 /*
1606 * 8.2 Step 7 / 8.4 Step 6.
1607 * Add decrypted Code, options and payload
1608 * [OSCORE option not copied across previously]
1609 */
1610
1611 /* PDU code is pseudo plain_pdu token */
1612 decrypt_pdu->code = plain_pdu->token[0];
1613
1614 /* Copy inner decrypted options across */
1615 coap_option_iterator_init(plain_pdu, &opt_iter, COAP_OPT_ALL);
1616 while ((opt = coap_option_next(&opt_iter))) {
1617 size_t len;
1618 size_t bias;
1619
1620 switch (opt_iter.number) {
1621 case COAP_OPTION_OSCORE:
1622 break;
1624 if (!coap_request) {
1625 bias = cose->partial_iv.length > 3 ? cose->partial_iv.length - 3 : 0;
1626 len = cose->partial_iv.length > 3 ? 3 : cose->partial_iv.length;
1627 /* Make Observe option reflect last 3 bytes of partial_iv */
1629 decrypt_pdu,
1630 opt_iter.number,
1631 len,
1632 cose->partial_iv.s ? &cose->partial_iv.s[bias] : NULL)) {
1635 session);
1636 goto error;
1637 }
1638 doing_resp_observe = 1;
1639 break;
1640 }
1641 association = oscore_find_association(session, &pdu_token);
1642 if (association) {
1643 association->is_observe = 1;
1644 association = NULL;
1645 }
1646 /* Fall Through */
1647 default:
1648 if (!coap_insert_option(decrypt_pdu,
1649 opt_iter.number,
1650 coap_opt_length(opt),
1651 coap_opt_value(opt))) {
1652 if (!coap_request)
1655 session);
1656 goto error;
1657 }
1658 break;
1659 }
1660 }
1661 if (!coap_request && !doing_resp_observe) {
1662 if (association) {
1663 association->is_observe = 0;
1664 }
1665 }
1666 /* Need to copy across any data */
1667 if (opt_iter.length > 0 && opt_iter.next_option &&
1668 opt_iter.next_option[0] == COAP_PAYLOAD_START) {
1669 plain_pdu->data = &opt_iter.next_option[1];
1670 if (!coap_add_data(decrypt_pdu,
1671 plain_pdu->used_size -
1672 (plain_pdu->data - plain_pdu->token),
1673 plain_pdu->data)) {
1674 if (!coap_request)
1677 session);
1678 goto error;
1679 }
1680 }
1681 coap_delete_pdu_lkd(plain_pdu);
1682 plain_pdu = NULL;
1683
1684 /* Make sure headers are correctly set up */
1685 if (!coap_pdu_encode_header(decrypt_pdu, session->proto)) {
1686 if (!coap_request)
1689 session);
1690 goto error;
1691 }
1692
1693 if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
1694 session->b_2_step = COAP_OSCORE_B_2_NONE;
1695 coap_log_oscore("Appendix B.2 client finished\n");
1696 }
1697#if COAP_CLIENT_SUPPORT
1698 if (decrypt_pdu->code == COAP_RESPONSE_CODE(401) &&
1699 (opt = coap_check_option(decrypt_pdu, COAP_OPTION_ECHO, &opt_iter))) {
1700 /* Server is requesting Echo refresh check */
1702 session,
1703 &pdu->actual_token);
1704 if (session->con_active)
1705 session->con_active--;
1706 if (!sent_pdu) {
1707 coap_lg_crcv_t *lg_crcv = coap_find_lg_crcv(session, pdu);
1708
1709 if (lg_crcv)
1710 sent_pdu = lg_crcv->sent_pdu;
1711 }
1712 if (sent_pdu) {
1713 coap_send_ack_lkd(session, pdu);
1714 coap_log_debug("PDU requesting re-transmit\n");
1715 coap_show_pdu(COAP_LOG_DEBUG, decrypt_pdu);
1716 coap_log_oscore("RFC9175 retransmit pdu\n");
1717 /* Do not care if this fails */
1718 if (coap_retransmit_oscore_pdu(session, sent_pdu, opt) != COAP_INVALID_MID) {
1719 session->doing_b_1_2 = 1;
1720 }
1721 goto error_no_ack;
1722 }
1723 } else if (session->doing_b_1_2) {
1724 coap_lg_crcv_t *lg_crcv = coap_find_lg_crcv(session, pdu);
1725
1726 if (lg_crcv) {
1727 if (!coap_binary_equal(&decrypt_pdu->actual_token, lg_crcv->app_token)) {
1728 coap_update_token(decrypt_pdu, lg_crcv->app_token->length, lg_crcv->app_token->s);
1729 }
1730 }
1731 session->doing_b_1_2 = 0;
1732 }
1733#endif /* COAP_CLIENT_SUPPORT */
1734 if (association && association->is_observe == 0)
1735 oscore_delete_association(session, association);
1736 return decrypt_pdu;
1737
1738error:
1739 coap_send_ack_lkd(session, pdu);
1740error_no_ack:
1741 if (association && association->is_observe == 0)
1742 oscore_delete_association(session, association);
1743 coap_delete_pdu_lkd(decrypt_pdu);
1744 coap_delete_pdu_lkd(plain_pdu);
1745 return NULL;
1746}
1747
1748typedef enum {
1749 COAP_ENC_ASCII = 0x001,
1750 COAP_ENC_HEX = 0x002,
1751 COAP_ENC_CONFIG = 0x0200,
1752 COAP_ENC_INTEGER = 0x400,
1753 COAP_ENC_TEXT = 0x800,
1754 COAP_ENC_BOOL = 0x1000,
1755 COAP_ENC_LAST
1756} coap_oscore_coding_t;
1757
1758#undef TEXT_MAPPING
1759#define TEXT_MAPPING(t, v) \
1760 { { sizeof(#t)-1, (const uint8_t *)#t }, v }
1761
1762static struct coap_oscore_encoding_t {
1763 coap_str_const_t name;
1764 coap_oscore_coding_t encoding;
1765} oscore_encoding[] = {
1766 TEXT_MAPPING(ascii, COAP_ENC_ASCII),
1767 TEXT_MAPPING(hex, COAP_ENC_HEX),
1768 TEXT_MAPPING(config, COAP_ENC_CONFIG),
1769 TEXT_MAPPING(integer, COAP_ENC_INTEGER),
1770 TEXT_MAPPING(text, COAP_ENC_TEXT),
1771 TEXT_MAPPING(bool, COAP_ENC_BOOL),
1772 {{0, NULL}, COAP_ENC_LAST}
1773};
1774
1775typedef struct {
1776 coap_oscore_coding_t encoding;
1777 const char *encoding_name;
1778 union {
1779 int value_int;
1780 coap_bin_const_t *value_bin;
1781 coap_str_const_t value_str;
1782 } u;
1783} oscore_value_t;
1784
1785/*
1786 * Return 1 if hex character
1787 * 0 not hex character
1788 */
1789static int
1790hex_to_char(char c, uint8_t *value) {
1791 if ('a' <= c && c <= 'f') {
1792 *value = c - 'a' + 10;
1793 } else if ('A' <= c && c <= 'F') {
1794 *value = c - 'A' + 10;
1795 } else if ('0' <= c && c <= '9') {
1796 *value = c - '0';
1797 } else {
1798 *value = 0;
1799 return 0;
1800 }
1801 return 1;
1802}
1803
1804/* Parse the hex into binary */
1805static coap_bin_const_t *
1806parse_hex_bin(const char *begin, const char *end) {
1807 coap_binary_t *binary = NULL;
1808 size_t i;
1809 size_t o = 0;
1810
1811 binary = coap_new_binary((end - begin) / 2);
1812 if (binary == NULL)
1813 goto bad_entry;
1814 for (i = 0; (i < (size_t)(end - begin)); i++) {
1815 while ((i < (size_t)(end - begin)) &&
1816 (begin[i] == '\r' || begin[i] == '\n' || begin[i] == ' ')) {
1817 i++;
1818 }
1819 if (i == (size_t)(end - begin))
1820 break;
1821 if (isxdigit((uint8_t)begin[i])) {
1822 uint8_t value;
1823
1824 if (!hex_to_char(begin[i], &value)) {
1825 goto bad_entry;
1826 }
1827 binary->s[o] = value << 4;
1828 i++;
1829 while ((i < (size_t)(end - begin)) &&
1830 (begin[i] == '\r' || begin[i] == '\n' || begin[i] == ' ')) {
1831 i++;
1832 }
1833 if (i == (size_t)(end - begin))
1834 goto bad_entry;
1835 if (!hex_to_char(begin[i], &value)) {
1836 goto bad_entry;
1837 }
1838 binary->s[o++] += value;
1839 } else {
1840 break;
1841 }
1842 }
1843 if (i != (size_t)(end - begin))
1844 goto bad_entry;
1845 return (coap_bin_const_t *)binary;
1846
1847bad_entry:
1848 coap_delete_binary(binary);
1849 return NULL;
1850}
1851
1852/*
1853 * Break up each OSCORE Configuration line entry into the 3 parts which
1854 * are comma separated
1855 *
1856 * keyword,encoding,value
1857 */
1858static int
1859get_split_entry(const char **start,
1860 size_t size,
1861 coap_str_const_t *keyword,
1862 oscore_value_t *value,
1863 cose_curve_t sign_curve) {
1864 const char *begin = *start;
1865 const char *keep_start = *start;
1866 const char *end;
1867 const char *kend;
1868 const char *tend;
1869 const char *split;
1870 size_t i;
1871 size_t len;
1872 (void)sign_curve;
1873
1874retry:
1875 kend = end = memchr(begin, '\n', size);
1876 if (end == NULL)
1877 return 0;
1878
1879 /* Check for multi-line */
1880 if ((tend = memchr(begin, '"', end - begin))) {
1881 /* See if " terminator is on the same line */
1882 if (!memchr(tend + 1, '"', end - tend -1)) {
1883 /* Over multiple lines */
1884 kend = end = memchr(end, '"', size - (end - begin));
1885 if (end == NULL)
1886 return 0;
1887 kend = end = memchr(kend, '\n', size - (kend - begin));
1888 if (end == NULL)
1889 return 0;
1890 }
1891 }
1892
1893 /* Track beginning of next line */
1894 *start = end + 1;
1895 if (end > begin && end[-1] == '\r')
1896 end--;
1897
1898 if (begin[0] == '#' || (end - begin) == 0) {
1899 /* Skip comment / blank line */
1900 size -= kend - begin + 1;
1901 begin = *start;
1902 keep_start = *start;
1903 goto retry;
1904 }
1905
1906 /* Get in the keyword */
1907 split = memchr(begin, ',', end - begin);
1908 if (split == NULL)
1909 goto bad_entry;
1910
1911 keyword->s = (const uint8_t *)begin;
1912 keyword->length = split - begin;
1913
1914 begin = split + 1;
1915 if ((end - begin) == 0)
1916 goto bad_entry;
1917 /* Get in the encoding */
1918 split = memchr(begin, ',', end - begin);
1919 if (split == NULL)
1920 goto bad_entry;
1921
1922 for (i = 0; oscore_encoding[i].name.s; i++) {
1923 coap_str_const_t temp = { split - begin, (const uint8_t *)begin };
1924
1925 if (coap_string_equal(&temp, &oscore_encoding[i].name)) {
1926 value->encoding = oscore_encoding[i].encoding;
1927 value->encoding_name = (const char *)oscore_encoding[i].name.s;
1928 break;
1929 }
1930 }
1931 if (oscore_encoding[i].name.s == NULL)
1932 goto bad_entry;
1933
1934 begin = split + 1;
1935 if ((end - begin) == 0)
1936 goto bad_entry;
1937 /* Get in the keyword's value */
1938 if (value->encoding == COAP_ENC_CONFIG && begin[0] == '\'') {
1939 split = memchr(&begin[1], '\'', size - (begin - keep_start) - 1);
1940 if (split == NULL)
1941 goto bad_entry;
1942 end = memchr(split, '\n', size - (split - keep_start));
1943 if (end == NULL)
1944 return 0;
1945 *start = end + 1;
1946 end = split;
1947 begin++;
1948 } else {
1949 if (begin[0] == '"') {
1950 split = memchr(&begin[1], '"', end - split - 1);
1951 if (split == NULL)
1952 goto bad_entry;
1953 end = split;
1954 begin++;
1955 }
1956 }
1957 switch (value->encoding) {
1958 case COAP_ENC_CONFIG:
1959 case COAP_ENC_ASCII:
1960 value->u.value_bin =
1961 coap_new_bin_const((const uint8_t *)begin, end - begin);
1962 if (value->u.value_bin == NULL)
1963 goto bad_entry;
1964 break;
1965 case COAP_ENC_HEX:
1966 /* Parse the hex into binary */
1967 value->u.value_bin = parse_hex_bin(begin, end);
1968 if (value->u.value_bin == NULL)
1969 goto bad_entry;
1970 break;
1971 case COAP_ENC_INTEGER:
1972 value->u.value_int = atoi(begin);
1973 break;
1974 case COAP_ENC_TEXT:
1975 value->u.value_str.s = (const uint8_t *)begin;
1976 value->u.value_str.length = end - begin;
1977 break;
1978 case COAP_ENC_BOOL:
1979 len = (size_t)(end - begin);
1980 if (len == 4 && memcmp("true", begin, len) == 0)
1981 value->u.value_int = 1;
1982 else if (len == 5 && memcmp("false", begin, len) == 0)
1983 value->u.value_int = 0;
1984 else
1985 goto bad_entry;
1986 break;
1987 case COAP_ENC_LAST:
1988 default:
1989 goto bad_entry;
1990 }
1991 return 1;
1992
1993bad_entry:
1994 coap_log_warn("oscore_conf: Unrecognized configuration entry '%.*s'\n",
1995 (int)(end - begin),
1996 begin);
1997 return -1;
1998
1999}
2000
2001#undef CONFIG_ENTRY
2002#define CONFIG_ENTRY(n, e, t) \
2003 { { sizeof(#n)-1, (const uint8_t *)#n }, e, \
2004 offsetof(coap_oscore_conf_t, n), t }
2005
2006#undef CONFIG_SND_ENTRY
2007#define CONFIG_SND_ENTRY(n, e, t) \
2008 { { sizeof(#n)-1, (const uint8_t *)#n }, e, \
2009 offsetof(coap_oscore_snd_conf_t, n), t }
2010
2011#undef CONFIG_RCP_ENTRY
2012#define CONFIG_RCP_ENTRY(n, e, t) \
2013 { { sizeof(#n)-1, (const uint8_t *)#n }, e, \
2014 offsetof(coap_oscore_rcp_conf_t, n), t }
2015
2016#undef CONFIG_DUMMY_ENTRY
2017#define CONFIG_DUMMY_ENTRY(n, e, t) \
2018 { { sizeof(#n)-1, (const uint8_t *)#n }, e, 0, t }
2019
2020typedef struct oscore_text_mapping_t {
2021 coap_str_const_t text;
2022 int value;
2023} oscore_text_mapping_t;
2024
2025/* Naming as per https://www.iana.org/assignments/cose/cose.xhtml#algorithms */
2026static oscore_text_mapping_t text_aead_alg[] = {
2027 TEXT_MAPPING(AES-CCM-16-64-128, COSE_ALGORITHM_AES_CCM_16_64_128),
2028 TEXT_MAPPING(AES-CCM-16-64-256, COSE_ALGORITHM_AES_CCM_16_64_256),
2029 {{0, NULL}, 0}
2030};
2031
2032static oscore_text_mapping_t text_hkdf_alg[] = {
2033 TEXT_MAPPING(direct+HKDF-SHA-256, COSE_HKDF_ALG_HKDF_SHA_256),
2034 {{0, NULL}, 0}
2035};
2036
2037typedef struct oscore_config_t {
2038 coap_str_const_t str_keyword;
2039 coap_oscore_coding_t encoding;
2040 size_t offset;
2041 oscore_text_mapping_t *text_mapping;
2042} oscore_config_t;
2043
2044static oscore_config_t oscore_config[] = {
2045 CONFIG_ENTRY(aead_alg, COAP_ENC_INTEGER | COAP_ENC_TEXT, text_aead_alg),
2046 CONFIG_ENTRY(hkdf_alg, COAP_ENC_INTEGER | COAP_ENC_TEXT, text_hkdf_alg),
2047 CONFIG_ENTRY(master_secret, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2048 CONFIG_ENTRY(master_salt, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2049 CONFIG_ENTRY(id_context, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2050
2051 CONFIG_DUMMY_ENTRY(sender_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2052
2053 CONFIG_DUMMY_ENTRY(recipient_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2054
2055 CONFIG_ENTRY(replay_window, COAP_ENC_INTEGER, NULL),
2056 CONFIG_ENTRY(ssn_freq, COAP_ENC_INTEGER, NULL),
2057 CONFIG_ENTRY(rfc8613_b_1_2, COAP_ENC_BOOL, NULL),
2058 CONFIG_ENTRY(rfc8613_b_2, COAP_ENC_BOOL, NULL),
2059 CONFIG_ENTRY(break_sender_key, COAP_ENC_BOOL, NULL),
2060 CONFIG_ENTRY(break_recipient_key, COAP_ENC_BOOL, NULL),
2061 CONFIG_DUMMY_ENTRY(complex_sender, COAP_ENC_CONFIG, NULL),
2062 CONFIG_DUMMY_ENTRY(complex_recipient, COAP_ENC_CONFIG, NULL),
2063};
2064
2065static oscore_config_t oscore_snd_config[] = {
2066 CONFIG_SND_ENTRY(sender_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2067};
2068
2069static oscore_config_t oscore_rcp_config[] = {
2070 CONFIG_RCP_ENTRY(recipient_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
2071 CONFIG_RCP_ENTRY(silent_server, COAP_ENC_BOOL, NULL),
2072};
2073
2074
2075int
2077 if (snd_conf == NULL)
2078 return 0;
2079
2081 coap_free_type(COAP_STRING, snd_conf);
2082 return 1;
2083}
2084
2085int
2087 if (rcp_conf == NULL)
2088 return 0;
2089
2091 coap_free_type(COAP_STRING, rcp_conf);
2092 return 1;
2093}
2094
2095int
2097 coap_oscore_rcp_conf_t *rcp_conf;
2098 if (oscore_conf == NULL)
2099 return 0;
2100
2102 coap_delete_bin_const(oscore_conf->master_salt);
2103 coap_delete_bin_const(oscore_conf->id_context);
2104 coap_delete_oscore_snd_conf(oscore_conf->sender);
2105
2106 rcp_conf = oscore_conf->recipient_chain;
2107 while (rcp_conf) {
2108 coap_oscore_rcp_conf_t *rcp_next = rcp_conf->next_recipient;
2109
2111 rcp_conf = rcp_next;
2112 }
2113
2114 coap_free_type(COAP_STRING, oscore_conf);
2115 return 1;
2116}
2117
2119coap_parse_oscore_snd_conf_mem(coap_bin_const_t conf_mem) {
2120 const char *start = (const char *)conf_mem.s;
2121 const char *end = start + conf_mem.length;
2122 coap_str_const_t keyword;
2123 oscore_value_t value;
2124 coap_oscore_snd_conf_t *snd_conf;
2125
2127 if (snd_conf == NULL)
2128 return NULL;
2129 memset(snd_conf, 0, sizeof(coap_oscore_snd_conf_t));
2130
2131 memset(&value, 0, sizeof(value));
2132
2133 while (end > start &&
2134 get_split_entry(&start, end - start, &keyword, &value, 0)) {
2135 size_t i;
2136 size_t j;
2137
2138 for (i = 0; i < sizeof(oscore_snd_config) / sizeof(oscore_snd_config[0]); i++) {
2139 if (coap_string_equal(&oscore_snd_config[i].str_keyword, &keyword) != 0 &&
2140 value.encoding & oscore_snd_config[i].encoding) {
2141 coap_bin_const_t *unused_check;
2142
2143 switch (value.encoding) {
2144 case COAP_ENC_HEX:
2145 case COAP_ENC_ASCII:
2146 memcpy(&unused_check,
2147 &(((char *)snd_conf)[oscore_snd_config[i].offset]),
2148 sizeof(unused_check));
2149 if (unused_check != NULL) {
2150 coap_log_warn("oscore_snd_conf: Keyword '%.*s' duplicated\n",
2151 (int)keyword.length,
2152 (const char *)keyword.s);
2153 goto error;
2154 }
2155 memcpy(&(((char *)snd_conf)[oscore_snd_config[i].offset]),
2156 &value.u.value_bin,
2157 sizeof(value.u.value_bin));
2158 break;
2159 case COAP_ENC_INTEGER:
2160 case COAP_ENC_BOOL:
2161 memcpy(&(((char *)snd_conf)[oscore_snd_config[i].offset]),
2162 &value.u.value_int,
2163 sizeof(value.u.value_int));
2164 break;
2165 case COAP_ENC_TEXT:
2166 for (j = 0; oscore_snd_config[i].text_mapping[j].text.s != NULL; j++) {
2167 if (memcmp(value.u.value_str.s,
2168 oscore_snd_config[i].text_mapping[j].text.s,
2169 value.u.value_str.length) == 0) {
2170 memcpy(&(((char *)snd_conf)[oscore_snd_config[i].offset]),
2171 &oscore_snd_config[i].text_mapping[j].value,
2172 sizeof(oscore_snd_config[i].text_mapping[j].value));
2173 break;
2174 }
2175 }
2176 if (oscore_snd_config[i].text_mapping[j].text.s == NULL) {
2177 coap_log_warn("oscore_snd_conf: Keyword '%.*s': value '%.*s' unknown\n",
2178 (int)keyword.length,
2179 (const char *)keyword.s,
2180 (int)value.u.value_str.length,
2181 (const char *)value.u.value_str.s);
2182 goto error;
2183 }
2184 break;
2185 case COAP_ENC_CONFIG:
2186 case COAP_ENC_LAST:
2187 default:
2188 assert(0);
2189 break;
2190 }
2191 break;
2192 }
2193 }
2194 if (i == sizeof(oscore_snd_config) / sizeof(oscore_snd_config[0])) {
2195 coap_log_warn("oscore_snd_conf: Keyword '%.*s', type '%s' unknown\n",
2196 (int)keyword.length,
2197 (const char *)keyword.s,
2198 value.encoding_name);
2199 if (value.encoding == COAP_ENC_HEX || value.encoding == COAP_ENC_ASCII)
2200 coap_delete_bin_const(value.u.value_bin);
2201 goto error;
2202 }
2203 }
2204 if (!snd_conf->sender_id) {
2205 coap_log_warn("oscore_snd_conf: sender_id not defined\n");
2206 goto error;
2207 }
2208 if (snd_conf->sender_id->length > 7) {
2209 coap_log_warn("oscore_snd_conf: Maximum size of sender_id is 7 bytes\n");
2210 goto error;
2211 }
2212 return snd_conf;
2213
2214error:
2216 return NULL;
2217}
2218
2220coap_parse_oscore_rcp_conf_mem(coap_bin_const_t conf_mem) {
2221 const char *start = (const char *)conf_mem.s;
2222 const char *end = start + conf_mem.length;
2223 coap_str_const_t keyword;
2224 oscore_value_t value;
2225 coap_oscore_rcp_conf_t *rcp_conf;
2226
2228 if (rcp_conf == NULL)
2229 return NULL;
2230 memset(rcp_conf, 0, sizeof(coap_oscore_rcp_conf_t));
2231
2232 memset(&value, 0, sizeof(value));
2233
2234 while (end > start &&
2235 get_split_entry(&start, end - start, &keyword, &value, 0)) {
2236 size_t i;
2237 size_t j;
2238
2239 for (i = 0; i < sizeof(oscore_rcp_config) / sizeof(oscore_rcp_config[0]); i++) {
2240 if (coap_string_equal(&oscore_rcp_config[i].str_keyword, &keyword) != 0 &&
2241 value.encoding & oscore_rcp_config[i].encoding) {
2242 coap_bin_const_t *unused_check;
2243
2244 switch (value.encoding) {
2245 case COAP_ENC_HEX:
2246 case COAP_ENC_ASCII:
2247 memcpy(&unused_check,
2248 &(((char *)rcp_conf)[oscore_rcp_config[i].offset]),
2249 sizeof(unused_check));
2250 if (unused_check != NULL) {
2251 coap_log_warn("oscore_rcp_conf: Keyword '%.*s' duplicated\n",
2252 (int)keyword.length,
2253 (const char *)keyword.s);
2254 goto error;
2255 }
2256 memcpy(&(((char *)rcp_conf)[oscore_rcp_config[i].offset]),
2257 &value.u.value_bin,
2258 sizeof(value.u.value_bin));
2259 break;
2260 case COAP_ENC_INTEGER:
2261 case COAP_ENC_BOOL:
2262 memcpy(&(((char *)rcp_conf)[oscore_rcp_config[i].offset]),
2263 &value.u.value_int,
2264 sizeof(value.u.value_int));
2265 break;
2266 case COAP_ENC_TEXT:
2267 for (j = 0; oscore_rcp_config[i].text_mapping[j].text.s != NULL; j++) {
2268 if (memcmp(value.u.value_str.s,
2269 oscore_rcp_config[i].text_mapping[j].text.s,
2270 value.u.value_str.length) == 0) {
2271 memcpy(&(((char *)rcp_conf)[oscore_rcp_config[i].offset]),
2272 &oscore_rcp_config[i].text_mapping[j].value,
2273 sizeof(oscore_rcp_config[i].text_mapping[j].value));
2274 break;
2275 }
2276 }
2277 if (oscore_rcp_config[i].text_mapping[j].text.s == NULL) {
2278 coap_log_warn("oscore_rcp_conf: Keyword '%.*s': value '%.*s' unknown\n",
2279 (int)keyword.length,
2280 (const char *)keyword.s,
2281 (int)value.u.value_str.length,
2282 (const char *)value.u.value_str.s);
2283 goto error;
2284 }
2285 break;
2286 case COAP_ENC_CONFIG:
2287 case COAP_ENC_LAST:
2288 default:
2289 assert(0);
2290 break;
2291 }
2292 break;
2293 }
2294 }
2295 if (i == sizeof(oscore_rcp_config) / sizeof(oscore_rcp_config[0])) {
2296 coap_log_warn("oscore_rcp_conf: Keyword '%.*s', type '%s' unknown\n",
2297 (int)keyword.length,
2298 (const char *)keyword.s,
2299 value.encoding_name);
2300 if (value.encoding == COAP_ENC_HEX || value.encoding == COAP_ENC_ASCII)
2301 coap_delete_bin_const(value.u.value_bin);
2302 goto error;
2303 }
2304 }
2305 if (!rcp_conf->recipient_id) {
2306 coap_log_warn("oscore_rcp_conf: recipient_id not defined\n");
2307 goto error;
2308 }
2309 if (rcp_conf->recipient_id->length > 7) {
2310 coap_log_warn("oscore_rcp_conf: Maximum size of recipient_id is 7 bytes\n");
2311 goto error;
2312 }
2313 return rcp_conf;
2314
2315error:
2317 return NULL;
2318}
2319
2320static coap_oscore_conf_t *
2321coap_parse_oscore_conf_mem(coap_str_const_t conf_mem) {
2322 const char *start = (const char *)conf_mem.s;
2323 const char *end = start + conf_mem.length;
2324 coap_str_const_t keyword;
2325 oscore_value_t value;
2326 coap_oscore_conf_t *oscore_conf;
2327 int split_ok = -1;
2328
2329 oscore_conf = coap_malloc_type(COAP_STRING, sizeof(coap_oscore_conf_t));
2330 if (oscore_conf == NULL)
2331 return NULL;
2332 memset(oscore_conf, 0, sizeof(coap_oscore_conf_t));
2333
2334 memset(&value, 0, sizeof(value));
2335 /* Preset with defaults RFC8612 3.2 */
2337 oscore_conf->ssn_freq = 1;
2339 oscore_conf->hkdf_alg = COSE_HKDF_ALG_HKDF_SHA_256;
2340
2341 oscore_conf->rfc8613_b_1_2 = 1;
2342 oscore_conf->rfc8613_b_2 = 0;
2343 /* For debugging only */
2344 oscore_conf->break_sender_key = 0;
2345 oscore_conf->break_recipient_key = 0;
2346
2347 while (end > start &&
2348 (split_ok = get_split_entry(&start, end - start, &keyword, &value, 0)) > 0) {
2349 size_t i;
2350 size_t j;
2351
2352 for (i = 0; i < sizeof(oscore_config) / sizeof(oscore_config[0]); i++) {
2353 if (coap_string_equal(&oscore_config[i].str_keyword, &keyword) != 0 &&
2354 value.encoding & oscore_config[i].encoding) {
2355 if (coap_string_equal(coap_make_str_const("sender_id"), &keyword)) {
2356 if (value.u.value_bin->length > 7) {
2357 coap_log_warn("oscore_conf: Maximum size of sender_id is 7 bytes\n");
2358 goto error_free_value_bin;
2359 }
2360 /* Special case group overlap */
2361 coap_delete_oscore_snd_conf(oscore_conf->sender);
2363 if (!oscore_conf->sender)
2364 goto error_free_value_bin;
2365
2366 memset(oscore_conf->sender, 0, sizeof(coap_oscore_snd_conf_t));
2367 oscore_conf->sender->sender_id = value.u.value_bin;
2368 } else if (coap_string_equal(coap_make_str_const("recipient_id"), &keyword)) {
2369 coap_oscore_rcp_conf_t *rcp_conf;
2370
2371 if (value.u.value_bin->length > 7) {
2372 coap_log_warn("oscore_conf: Maximum size of recipient_id is 7 bytes\n");
2373 goto error_free_value_bin;
2374 }
2375 /* Special case as there are potentially multiple entries */
2377 if (!rcp_conf)
2378 goto error_free_value_bin;
2379
2380 memset(rcp_conf, 0, sizeof(coap_oscore_rcp_conf_t));
2381 rcp_conf->recipient_id = value.u.value_bin;
2382 rcp_conf->next_recipient = oscore_conf->recipient_chain;
2383 oscore_conf->recipient_chain = rcp_conf;
2384 } else {
2385 coap_bin_const_t *unused_check;
2386
2387 switch (value.encoding) {
2388 case COAP_ENC_CONFIG:
2389 if (keyword.length == sizeof("complex_sender") - 1 &&
2390 memcmp(keyword.s, "complex_sender", keyword.length) == 0) {
2391 coap_oscore_snd_conf_t *snd_conf =
2392 coap_parse_oscore_snd_conf_mem(*value.u.value_bin);
2393
2394 if (!snd_conf) {
2395 coap_log_warn("oscore_conf: Keyword '%.*s' invalid\n",
2396 (int)keyword.length,
2397 (const char *)keyword.s);
2398 goto error_free_value_bin;
2399 }
2400 if (oscore_conf->sender) {
2401 coap_log_warn("oscore_conf: group sender duplicated\n");
2402 goto error_free_value_bin;
2403 }
2404 oscore_conf->sender = snd_conf;
2405 coap_delete_bin_const(value.u.value_bin);
2406 break;
2407 }
2408 if (keyword.length == sizeof("complex_recipient") - 1 &&
2409 memcmp(keyword.s, "complex_recipient", keyword.length) == 0) {
2410 coap_oscore_rcp_conf_t *rcp_conf =
2411 coap_parse_oscore_rcp_conf_mem(*value.u.value_bin);
2412
2413 if (!rcp_conf) {
2414 coap_log_warn("oscore_conf: Keyword '%.*s' invalid\n",
2415 (int)keyword.length,
2416 (const char *)keyword.s);
2417 goto error_free_value_bin;
2418 }
2419 rcp_conf->next_recipient = oscore_conf->recipient_chain;
2420 oscore_conf->recipient_chain = rcp_conf;
2421 coap_delete_bin_const(value.u.value_bin);
2422 }
2423 break;
2424 case COAP_ENC_ASCII:
2425 case COAP_ENC_HEX:
2426 memcpy(&unused_check,
2427 &(((char *)oscore_conf)[oscore_config[i].offset]),
2428 sizeof(unused_check));
2429 if (unused_check != NULL) {
2430 coap_log_warn("oscore_conf: Keyword '%.*s' duplicated\n",
2431 (int)keyword.length,
2432 (const char *)keyword.s);
2433 goto error_free_value_bin;
2434 }
2435 memcpy(&(((char *)oscore_conf)[oscore_config[i].offset]),
2436 &value.u.value_bin,
2437 sizeof(value.u.value_bin));
2438 break;
2439 case COAP_ENC_INTEGER:
2440 case COAP_ENC_BOOL:
2441 memcpy(&(((char *)oscore_conf)[oscore_config[i].offset]),
2442 &value.u.value_int,
2443 sizeof(value.u.value_int));
2444 break;
2445 case COAP_ENC_TEXT:
2446 for (j = 0; oscore_config[i].text_mapping[j].text.s != NULL; j++) {
2447 if (coap_string_equal(&value.u.value_str,
2448 &oscore_config[i].text_mapping[j].text)) {
2449 memcpy(&(((char *)oscore_conf)[oscore_config[i].offset]),
2450 &oscore_config[i].text_mapping[j].value,
2451 sizeof(oscore_config[i].text_mapping[j].value));
2452 break;
2453 }
2454 }
2455 if (oscore_config[i].text_mapping[j].text.s == NULL) {
2456 coap_log_warn("oscore_conf: Keyword '%.*s': value '%.*s' unknown\n",
2457 (int)keyword.length,
2458 (const char *)keyword.s,
2459 (int)value.u.value_str.length,
2460 (const char *)value.u.value_str.s);
2461 goto error;
2462 }
2463 break;
2464 case COAP_ENC_LAST:
2465 default:
2466 assert(0);
2467 break;
2468 }
2469 }
2470 break;
2471 }
2472 }
2473 if (i == sizeof(oscore_config) / sizeof(oscore_config[0])) {
2474 coap_log_warn("oscore_conf: Keyword '%.*s', type '%s' unknown\n",
2475 (int)keyword.length,
2476 (const char *)keyword.s,
2477 value.encoding_name);
2478 if (value.encoding == COAP_ENC_HEX || value.encoding == COAP_ENC_ASCII ||
2479 value.encoding == COAP_ENC_CONFIG) {
2480 coap_delete_bin_const(value.u.value_bin);
2481 }
2482 goto error;
2483 }
2484 }
2485 if (split_ok == -1)
2486 goto error;
2487 if (!oscore_conf->master_secret) {
2488 coap_log_warn("oscore_conf: master_secret not defined\n");
2489 goto error;
2490 }
2491 if (!oscore_conf->sender) {
2492 coap_log_warn("oscore_conf: sender_id not defined\n");
2493 goto error;
2494 }
2495 return oscore_conf;
2496
2497error_free_value_bin:
2498 coap_delete_bin_const(value.u.value_bin);
2499error:
2500 coap_delete_oscore_conf(oscore_conf);
2501 return NULL;
2502}
2503
2504static oscore_ctx_t *
2505coap_oscore_init(coap_context_t *c_context, coap_oscore_conf_t *oscore_conf) {
2506 oscore_ctx_t *osc_ctx = NULL;
2507
2508 if (!coap_crypto_check_cipher_alg(oscore_conf->aead_alg)) {
2509 coap_log_warn("COSE: Cipher Algorithm %d not supported\n",
2510 oscore_conf->aead_alg);
2511 goto error;
2512 }
2513 if (!coap_crypto_check_hkdf_alg(oscore_conf->hkdf_alg)) {
2514 coap_log_warn("COSE: HKDF Algorithm %d not supported\n",
2515 oscore_conf->hkdf_alg);
2516 goto error;
2517 }
2518
2519 osc_ctx = oscore_derive_ctx(c_context, oscore_conf);
2520 if (!osc_ctx) {
2521 coap_log_crit("OSCORE: Could not create Security Context!\n");
2522 coap_free_type(COAP_STRING, oscore_conf);
2523 return NULL;
2524 }
2525
2526 /* As all is stored in osc_ctx, oscore_conf is no longer needed */
2527 coap_free_type(COAP_STRING, oscore_conf);
2528
2529 /* return default first context */
2530 return osc_ctx;
2531
2532error:
2533 /* Remove from linked chain */
2534 oscore_remove_context(c_context, osc_ctx);
2535
2536 coap_delete_oscore_conf(oscore_conf);
2537 return NULL;
2538}
2539
2540void
2542 oscore_free_contexts(c_context);
2543}
2544
2545void
2548}
2549
2552 coap_oscore_save_seq_num_t save_seq_num_func,
2553 void *save_seq_num_func_param,
2554 uint64_t start_seq_num) {
2555 coap_oscore_conf_t *oscore_conf = coap_parse_oscore_conf_mem(conf_mem);
2556
2557 if (oscore_conf == NULL)
2558 return NULL;
2559
2560 oscore_conf->save_seq_num_func = save_seq_num_func;
2561 oscore_conf->save_seq_num_func_param = save_seq_num_func_param;
2562 oscore_conf->start_seq_num = start_seq_num;
2563 coap_log_oscore("Start Seq no %" PRIu64 "\n", start_seq_num);
2564 return oscore_conf;
2565}
2566
2567/*
2568 * Compute the size of the potential OSCORE overhead
2569 */
2570size_t
2572 size_t overhead = 0;
2573 oscore_recipient_ctx_t *rcp_ctx = session->recipient_ctx;
2574 oscore_ctx_t *osc_ctx = rcp_ctx ? rcp_ctx->osc_ctx : NULL;
2575 coap_opt_iterator_t opt_iter;
2576 coap_opt_t *option;
2577
2578 if (osc_ctx == NULL)
2579 return 0;
2580
2581 /* Protected code held in inner PDU as token */
2582 overhead += 1;
2583
2584 /* Observe option (creates inner and outer */
2585 option = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter);
2586 if (option) {
2587 /* Assume delta is small */
2588 overhead += 2 + coap_opt_length(option);
2589 }
2590
2591 /* Proxy URI option Split - covered by coap_rebuild_pdu_for_proxy () */
2592
2593 /* OSCORE option */
2594 /* Option header */
2595 overhead += 1 +
2596 /* Partial IV (64 bits max)*/
2597 8 +
2598 /* kid context */
2599 (osc_ctx->id_context ? osc_ctx->id_context->length : 0) +
2600 /* kid */
2601 osc_ctx->sender_context->sender_id->length;
2602
2603 /* AAD overhead */
2604 overhead += AES_CCM_TAG;
2605
2606 /* End of options marker */
2607 overhead += 1;
2608
2609 return overhead;
2610}
2611
2612COAP_API int
2614 coap_bin_const_t *recipient_id) {
2615 int ret;
2616
2617 coap_lock_lock(return 0);
2618 ret = coap_new_oscore_recipient_lkd(context, recipient_id);
2620 return ret;
2621}
2622
2623int
2625 coap_bin_const_t *recipient_id) {
2626 coap_oscore_rcp_conf_t *rcp_conf;
2627
2629
2630 if (context->p_osc_ctx == NULL) {
2631 coap_delete_bin_const(recipient_id);
2632 return 0;
2633 }
2635 if (rcp_conf == NULL) {
2636 coap_delete_bin_const(recipient_id);
2637 return 0;
2638 }
2639 memset(rcp_conf, 0, sizeof(coap_oscore_rcp_conf_t));
2640 rcp_conf->recipient_id = recipient_id;
2641 /* rcp_conf is released in oscore_add_recipient() */
2642 if (oscore_add_recipient(context->p_osc_ctx, rcp_conf, 0) == NULL)
2643 return 0;
2644 return 1;
2645}
2646
2647COAP_API int
2649 coap_bin_const_t *recipient_id) {
2650 int ret;
2651
2652 if (!context || !recipient_id)
2653 return 0;
2654 coap_lock_lock(return 0);
2655 ret = coap_delete_oscore_recipient_lkd(context, recipient_id);
2657 return ret;
2658}
2659
2660int
2662 coap_bin_const_t *recipient_id) {
2664 if (context->p_osc_ctx == NULL)
2665 return 0;
2666 return oscore_delete_recipient(context->p_osc_ctx, recipient_id);
2667}
2668
2671#else /* !COAP_OSCORE_SUPPORT */
2672int
2674 return 0;
2675}
2676
2679 const coap_address_t *local_if,
2680 const coap_address_t *server,
2681 coap_proto_t proto,
2682 coap_oscore_conf_t *oscore_conf) {
2683 (void)ctx;
2684 (void)local_if;
2685 (void)server;
2686 (void)proto;
2687 (void)oscore_conf;
2688 return NULL;
2689}
2690
2693 const coap_address_t *local_if,
2694 const coap_address_t *server,
2695 coap_proto_t proto,
2696 coap_oscore_conf_t *oscore_conf,
2697 void *app_data,
2699 coap_str_const_t *ws_host) {
2700 (void)ctx;
2701 (void)local_if;
2702 (void)server;
2703 (void)proto;
2704 (void)oscore_conf;
2705 (void)app_data;
2706 (void)callback;
2707 (void)ws_host;
2708 return NULL;
2709}
2710
2713 const coap_address_t *local_if,
2714 const coap_address_t *server,
2715 coap_proto_t proto,
2716 coap_dtls_cpsk_t *psk_data,
2717 coap_oscore_conf_t *oscore_conf) {
2718 (void)ctx;
2719 (void)local_if;
2720 (void)server;
2721 (void)proto;
2722 (void)psk_data;
2723 (void)oscore_conf;
2724 return NULL;
2725}
2726
2729 const coap_address_t *local_if,
2730 const coap_address_t *server,
2731 coap_proto_t proto,
2732 coap_dtls_cpsk_t *psk_data,
2733 coap_oscore_conf_t *oscore_conf,
2734 void *app_data,
2736 coap_str_const_t *ws_host) {
2737 (void)ctx;
2738 (void)local_if;
2739 (void)server;
2740 (void)proto;
2741 (void)psk_data;
2742 (void)oscore_conf;
2743 (void)app_data;
2744 (void)callback;
2745 (void)ws_host;
2746 return NULL;
2747}
2748
2751 const coap_address_t *local_if,
2752 const coap_address_t *server,
2753 coap_proto_t proto,
2754 coap_dtls_pki_t *pki_data,
2755 coap_oscore_conf_t *oscore_conf) {
2756 (void)ctx;
2757 (void)local_if;
2758 (void)server;
2759 (void)proto;
2760 (void)pki_data;
2761 (void)oscore_conf;
2762 return NULL;
2763}
2764
2767 const coap_address_t *local_if,
2768 const coap_address_t *server,
2769 coap_proto_t proto,
2770 coap_dtls_pki_t *pki_data,
2771 coap_oscore_conf_t *oscore_conf,
2772 void *app_data,
2774 coap_str_const_t *ws_host) {
2775 (void)ctx;
2776 (void)local_if;
2777 (void)server;
2778 (void)proto;
2779 (void)pki_data;
2780 (void)oscore_conf;
2781 (void)app_data;
2782 (void)callback;
2783 (void)ws_host;
2784 return NULL;
2785}
2786
2787int
2789 coap_oscore_conf_t *oscore_conf) {
2790 (void)context;
2791 (void)oscore_conf;
2792 return 0;
2793}
2794
2797 coap_oscore_save_seq_num_t save_seq_num_func,
2798 void *save_seq_num_func_param,
2799 uint64_t start_seq_num) {
2800 (void)conf_mem;
2801 (void)save_seq_num_func;
2802 (void)save_seq_num_func_param;
2803 (void)start_seq_num;
2804 return NULL;
2805}
2806
2807int
2809 (void)oscore_conf;
2810 return 0;
2811}
2812
2813int
2815 coap_bin_const_t *recipient_id) {
2816 (void)context;
2817 (void)recipient_id;
2818 return 0;
2819}
2820
2821int
2823 coap_bin_const_t *recipient_id) {
2824 (void)context;
2825 (void)recipient_id;
2826 return 0;
2827}
2828
2829#endif /* !COAP_OSCORE_SUPPORT */
struct coap_lg_crcv_t coap_lg_crcv_t
#define PRIu64
Library specific build wrapper for coap_internal.h.
#define COAP_API
@ COAP_OSCORE_BUF
Definition coap_mem.h:60
@ COAP_STRING
Definition coap_mem.h:33
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
#define NULL
Definition coap_option.h:30
uint8_t coap_opt_t
Use byte-oriented access methods here because sliding a complex struct coap_opt_t over the data buffe...
Definition coap_option.h:43
static int coap_uri_scheme_is_secure(const coap_uri_t *uri)
Definition coap_uri.h:86
@ COAP_URI_SCHEME_LAST
Definition coap_uri.h:39
coap_mid_t coap_send_ack_lkd(coap_session_t *session, const coap_pdu_t *request)
Sends an ACK message with code 0 for the specified request to dst.
Definition coap_net.c:1119
#define COAP_BLOCK_CACHE_RESPONSE
Definition coap_block.h:73
int coap_prng_lkd(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition coap_prng.c:190
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition coap_net.c:5079
uint16_t coap_new_message_id_lkd(coap_session_t *session)
Returns a new message id and updates session->tx_mid accordingly.
coap_mid_t coap_send_internal(coap_session_t *session, coap_pdu_t *pdu, coap_pdu_t *request_pdu)
Sends a CoAP message to given peer.
Definition coap_net.c:2007
void coap_cancel_all_messages(coap_context_t *context, coap_session_t *session, coap_bin_const_t *token)
Cancels all outstanding messages for session session that have the specified token.
Definition coap_net.c:3201
#define COAP_OSCORE_DEFAULT_REPLAY_WINDOW
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
unsigned int coap_encode_var_safe(uint8_t *buf, size_t length, unsigned int val)
Encodes multiple-length byte sequences.
Definition coap_encode.c:47
unsigned int coap_decode_var_bytes(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition coap_encode.c:38
uint64_t coap_decode_var_bytes8(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition coap_encode.c:71
unsigned int coap_encode_var_safe8(uint8_t *buf, size_t length, uint64_t val)
Encodes multiple-length byte sequences.
Definition coap_encode.c:81
@ COAP_EVENT_OSCORE_DECODE_ERROR
Triggered when there is an OSCORE decode of OSCORE option failure.
Definition coap_event.h:130
@ COAP_EVENT_OSCORE_INTERNAL_ERROR
Triggered when there is an OSCORE internal error i.e malloc failed.
Definition coap_event.h:128
@ COAP_EVENT_OSCORE_NOT_ENABLED
Triggered when trying to use OSCORE to decrypt, but it is not enabled.
Definition coap_event.h:122
@ COAP_EVENT_OSCORE_NO_SECURITY
Triggered when there is no OSCORE security definition found.
Definition coap_event.h:126
@ COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD
Triggered when there is no OSCORE encrypted payload provided.
Definition coap_event.h:124
@ COAP_EVENT_OSCORE_DECRYPTION_FAILURE
Triggered when there is an OSCORE decryption failure.
Definition coap_event.h:120
#define coap_lock_unlock()
Dummy for no thread-safe code.
#define coap_lock_check_locked()
Dummy for no thread-safe code.
#define coap_lock_lock(failed)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:126
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition coap_debug.c:103
void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu)
Display the contents of the specified pdu.
Definition coap_debug.c:793
#define coap_log_oscore(...)
Definition coap_debug.h:132
#define coap_log_warn(...)
Definition coap_debug.h:108
#define coap_log_err(...)
Definition coap_debug.h:102
#define coap_log_crit(...)
Definition coap_debug.h:96
@ COAP_LOG_OSCORE
Definition coap_debug.h:65
@ COAP_LOG_DEBUG
Definition coap_debug.h:64
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
coap_opt_iterator_t * coap_option_iterator_init(const coap_pdu_t *pdu, coap_opt_iterator_t *oi, const coap_opt_filter_t *filter)
Initializes the given option iterator oi to point to the beginning of the pdu's option list.
void coap_delete_optlist(coap_optlist_t *queue)
Removes all entries from the optlist_chain, freeing off their memory usage.
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t **options)
The current optlist of optlist_chain is first sorted (as per RFC7272 ordering requirements) and then ...
coap_opt_t * coap_check_option(const coap_pdu_t *pdu, coap_option_num_t number, coap_opt_iterator_t *oi)
Retrieves the first option of number number from pdu.
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
size_t oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_size)
void cose_encrypt0_set_plaintext(cose_encrypt0_t *ptr, uint8_t *buffer, size_t size)
int cose_encrypt0_set_key(cose_encrypt0_t *ptr, coap_bin_const_t *key)
void cose_encrypt0_set_kid_context(cose_encrypt0_t *ptr, coap_bin_const_t *kid_context)
const char * cose_get_alg_name(cose_alg_t id, char *buffer, size_t buflen)
void cose_encrypt0_set_ciphertext(cose_encrypt0_t *ptr, uint8_t *buffer, size_t size)
int cose_encrypt0_decrypt(cose_encrypt0_t *ptr, uint8_t *plaintext_buffer, size_t plaintext_len)
size_t cose_tag_len(cose_alg_t cose_alg)
void cose_encrypt0_set_aad(cose_encrypt0_t *ptr, coap_bin_const_t *aad)
cose_curve_t
Definition oscore_cose.h:62
int cose_encrypt0_encrypt(cose_encrypt0_t *ptr, uint8_t *ciphertext_buffer, size_t ciphertext_len)
void cose_encrypt0_set_partial_iv(cose_encrypt0_t *ptr, coap_bin_const_t *partial_iv)
void cose_encrypt0_set_external_aad(cose_encrypt0_t *ptr, coap_bin_const_t *external_aad)
void cose_encrypt0_init(cose_encrypt0_t *ptr)
void cose_encrypt0_set_alg(cose_encrypt0_t *ptr, uint8_t alg)
void cose_encrypt0_set_key_id(cose_encrypt0_t *ptr, coap_bin_const_t *key_id)
void cose_encrypt0_set_nonce(cose_encrypt0_t *ptr, coap_bin_const_t *nonce)
@ COSE_HKDF_ALG_HKDF_SHA_256
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_AES_CCM_16_64_256
size_t oscore_prepare_aad(const uint8_t *external_aad_buffer, size_t external_aad_len, uint8_t *aad_buffer, size_t aad_size)
size_t oscore_encode_option_value(uint8_t *option_buffer, size_t option_buf_len, cose_encrypt0_t *cose, uint8_t group, uint8_t appendix_b_2)
int coap_delete_oscore_recipient_lkd(coap_context_t *context, coap_bin_const_t *recipient_id)
Release all the information associated for the specific Recipient ID (and hence and stop any further ...
int oscore_delete_association(coap_session_t *session, oscore_association_t *association)
coap_session_t * coap_new_client_session_oscore3_lkd(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_oscore_conf_t *oscore_conf, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, protecting the data using OSCORE,...
uint8_t oscore_validate_sender_seq(oscore_recipient_ctx_t *ctx, cose_encrypt0_t *cose)
oscore_recipient_ctx_t * oscore_add_recipient(oscore_ctx_t *ctx, coap_oscore_rcp_conf_t *rcp_conf, uint32_t break_key)
oscore_add_recipient - add in recipient information
#define OSCORE_SEQ_MAX
#define AES_CCM_TAG
int oscore_decode_option_value(const uint8_t *option_value, size_t option_len, cose_encrypt0_t *cose)
int coap_delete_oscore_snd_conf(coap_oscore_snd_conf_t *oscore_snd_conf)
Release all the information associated with the OSCORE complex Sender configuration.
coap_pdu_t * coap_oscore_new_pdu_encrypted_lkd(coap_session_t *session, coap_pdu_t *pdu, coap_bin_const_t *kid_context, oscore_partial_iv_t send_partial_iv)
Encrypts the specified pdu when OSCORE encryption is required on session.
int oscore_delete_recipient(oscore_ctx_t *osc_ctx, coap_bin_const_t *rid)
uint8_t oscore_increment_sender_seq(oscore_ctx_t *ctx)
void oscore_update_ctx(oscore_ctx_t *osc_ctx, coap_bin_const_t *id_context)
oscore_update_ctx - update a osc_ctx with a new id_context
coap_session_t * coap_new_client_session_oscore_psk3_lkd(coap_context_t *ctx, 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, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PSK credentials protecting the data using...
oscore_ctx_t * oscore_derive_ctx(coap_context_t *c_context, coap_oscore_conf_t *oscore_conf)
oscore_derive_ctx - derive a osc_ctx from oscore_conf information
COAP_API coap_pdu_t * coap_oscore_new_pdu_encrypted(coap_session_t *session, coap_pdu_t *pdu, coap_bin_const_t *kid_context, oscore_partial_iv_t send_partial_iv)
Encrypts the specified pdu when OSCORE encryption is required on session.
void oscore_roll_back_seq(oscore_recipient_ctx_t *ctx)
int oscore_new_association(coap_session_t *session, coap_pdu_t *sent_pdu, coap_bin_const_t *token, oscore_recipient_ctx_t *recipient_ctx, coap_bin_const_t *aad, coap_bin_const_t *nonce, coap_bin_const_t *partial_iv, int is_observe)
size_t oscore_prepare_e_aad(oscore_ctx_t *ctx, cose_encrypt0_t *cose, const uint8_t *oscore_option, size_t oscore_option_len, coap_bin_const_t *sender_public_key, uint8_t *external_aad_ptr, size_t external_aad_size)
void oscore_delete_server_associations(coap_session_t *session)
void oscore_log_char_value(coap_log_t level, const char *name, const char *value)
struct coap_pdu_t * coap_oscore_decrypt_pdu(coap_session_t *session, coap_pdu_t *pdu)
Decrypts the OSCORE-encrypted parts of pdu when OSCORE is used.
int coap_rebuild_pdu_for_proxy(coap_pdu_t *pdu)
Convert PDU to use Proxy-Scheme option if Proxy-Uri option is present.
void oscore_free_contexts(coap_context_t *c_context)
void oscore_log_hex_value(coap_log_t level, const char *name, coap_bin_const_t *value)
void coap_delete_oscore_associations(coap_session_t *session)
Cleanup all allocated OSCORE association information.
int coap_oscore_initiate(coap_session_t *session, coap_oscore_conf_t *oscore_conf)
Initiate an OSCORE session.
int coap_new_oscore_recipient_lkd(coap_context_t *context, coap_bin_const_t *recipient_id)
Add in the specific Recipient ID into the OSCORE context (server only).
oscore_ctx_t * oscore_duplicate_ctx(coap_context_t *c_context, oscore_ctx_t *o_osc_ctx, coap_bin_const_t *sender_id, coap_bin_const_t *recipient_id, coap_bin_const_t *id_context)
oscore_duplicate_ctx - duplicate a osc_ctx
oscore_partial_iv_t
void coap_delete_all_oscore(coap_context_t *context)
Cleanup all allocated OSCORE information.
void oscore_generate_nonce(cose_encrypt0_t *ptr, oscore_ctx_t *ctx, uint8_t *buffer, uint8_t size)
int oscore_remove_context(coap_context_t *c_context, oscore_ctx_t *osc_ctx)
oscore_association_t * oscore_find_association(coap_session_t *session, coap_bin_const_t *token)
int coap_context_oscore_server_lkd(coap_context_t *context, coap_oscore_conf_t *oscore_conf)
Set the context's default OSCORE configuration for a server.
int coap_delete_oscore_rcp_conf(coap_oscore_rcp_conf_t *oscore_rcp_conf)
Release all the information associated with the OSCORE complex Recipient configuration.
oscore_ctx_t * oscore_find_context(const coap_session_t *session, const coap_bin_const_t rcpkey_id, const coap_bin_const_t *ctxkey_id, uint8_t *oscore_r2, oscore_recipient_ctx_t **recipient_ctx)
oscore_find_context - Locate recipient context (and hence OSCORE context)
coap_session_t * coap_new_client_session_oscore_pki3_lkd(coap_context_t *ctx, 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, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PKI credentials protecting the data using...
size_t coap_oscore_overhead(coap_session_t *session, coap_pdu_t *pdu)
Determine the additional data size requirements for adding in OSCORE.
@ OSCORE_SEND_PARTIAL_IV
Send partial IV with encrypted PDU.
@ OSCORE_SEND_NO_IV
Do not send partial IV unless added by a response.
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)
Parse an OSCORE configuration (held in memory) and populate a OSCORE configuration structure.
coap_session_t * coap_new_client_session_oscore_psk(coap_context_t *ctx, 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)
Creates a new client session to the designated server with PSK credentials as well as protecting the ...
coap_session_t * coap_new_client_session_oscore_psk3(coap_context_t *ctx, 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, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PSK credentials protecting the data using...
int coap_delete_oscore_conf(coap_oscore_conf_t *oscore_conf)
Release all the information associated with the OSCORE configuration.
coap_session_t * coap_new_client_session_oscore(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_oscore_conf_t *oscore_conf)
Creates a new client session to the designated server, protecting the data using OSCORE.
int coap_context_oscore_server(coap_context_t *context, coap_oscore_conf_t *oscore_conf)
Set the context's default OSCORE configuration for a server.
coap_session_t * coap_new_client_session_oscore_pki(coap_context_t *ctx, 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)
Creates a new client session to the designated server with PKI credentials as well as protecting the ...
coap_session_t * coap_new_client_session_oscore3(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_oscore_conf_t *oscore_conf, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, protecting the data using OSCORE,...
int coap_new_oscore_recipient(coap_context_t *context, coap_bin_const_t *recipient_id)
Add in the specific Recipient ID into the OSCORE context (server only).
int(* coap_oscore_save_seq_num_t)(uint64_t sender_seq_num, void *param)
Definition of the function used to save the current Sender Sequence Number.
int coap_delete_oscore_recipient(coap_context_t *context, coap_bin_const_t *recipient_id)
Release all the information associated for the specific Recipient ID (and hence and stop any further ...
coap_session_t * coap_new_client_session_oscore_pki3(coap_context_t *ctx, 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, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PKI credentials protecting the data using...
void coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:194
size_t coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Inserts option of given number in the pdu with the appropriate data.
Definition coap_pdu.c:652
int coap_remove_option(coap_pdu_t *pdu, coap_option_num_t number)
Removes (first) option of given number from the pdu.
Definition coap_pdu.c:512
int coap_update_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Updates token in pdu with length len and data.
Definition coap_pdu.c:436
#define COAP_PDU_IS_PING(pdu)
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto)
Compose the protocol specific header for the specified PDU.
Definition coap_pdu.c:1542
coap_pdu_t * coap_pdu_duplicate_lkd(const coap_pdu_t *old_pdu, coap_session_t *session, size_t token_length, const uint8_t *token, coap_opt_filter_t *drop_options)
Duplicate an existing PDU.
Definition coap_pdu.c:234
#define COAP_PAYLOAD_START
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size)
Dynamically grows the size of pdu to new_size.
Definition coap_pdu.c:307
#define COAP_PDU_IS_REQUEST(pdu)
size_t coap_add_option_internal(coap_pdu_t *pdu, coap_option_num_t number, size_t len, const uint8_t *data)
Adds option of given number to pdu that is passed as first parameter.
Definition coap_pdu.c:807
#define COAP_OPTION_HOP_LIMIT
Definition coap_pdu.h:135
#define COAP_OPTION_NORESPONSE
Definition coap_pdu.h:148
#define COAP_OPTION_URI_HOST
Definition coap_pdu.h:122
#define COAP_OPTION_IF_MATCH
Definition coap_pdu.h:121
#define COAP_OPTION_BLOCK2
Definition coap_pdu.h:140
#define COAP_OPTION_CONTENT_FORMAT
Definition coap_pdu.h:130
#define COAP_OPTION_SIZE2
Definition coap_pdu.h:142
#define COAP_OPTION_BLOCK1
Definition coap_pdu.h:141
#define COAP_OPTION_PROXY_SCHEME
Definition coap_pdu.h:145
#define COAP_DEFAULT_PORT
Definition coap_pdu.h:39
#define COAP_OPTION_URI_QUERY
Definition coap_pdu.h:134
#define COAP_OPTION_IF_NONE_MATCH
Definition coap_pdu.h:124
#define COAP_OPTION_LOCATION_PATH
Definition coap_pdu.h:127
#define COAP_OPTION_URI_PATH
Definition coap_pdu.h:129
#define COAP_RESPONSE_CODE(N)
Definition coap_pdu.h:163
#define COAP_RESPONSE_CLASS(C)
Definition coap_pdu.h:166
coap_proto_t
CoAP protocol types Note: coap_layers_coap[] needs updating if extended.
Definition coap_pdu.h:316
coap_pdu_code_t
Set of codes available for a PDU.
Definition coap_pdu.h:330
#define COAP_OPTION_OSCORE
Definition coap_pdu.h:128
#define COAP_OPTION_SIZE1
Definition coap_pdu.h:146
int coap_add_token(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds token of length len to pdu.
Definition coap_pdu.c:379
#define COAP_OPTION_LOCATION_QUERY
Definition coap_pdu.h:138
#define COAPS_DEFAULT_PORT
Definition coap_pdu.h:40
int coap_get_data(const coap_pdu_t *pdu, size_t *len, const uint8_t **data)
Retrieves the length and data pointer of specified PDU.
Definition coap_pdu.c:903
#define COAP_OPTION_RTAG
Definition coap_pdu.h:149
#define COAP_OPTION_URI_PORT
Definition coap_pdu.h:126
coap_pdu_t * coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, coap_mid_t mid, size_t size)
Creates a new CoAP PDU with at least enough storage space for the given size maximum message size.
Definition coap_pdu.c:102
#define COAP_OPTION_ACCEPT
Definition coap_pdu.h:136
#define COAP_INVALID_MID
Indicates an invalid message id.
Definition coap_pdu.h:269
#define COAP_OPTION_MAXAGE
Definition coap_pdu.h:133
#define COAP_OPTION_ETAG
Definition coap_pdu.h:123
#define COAP_OPTION_PROXY_URI
Definition coap_pdu.h:144
#define COAP_OPTION_OBSERVE
Definition coap_pdu.h:125
#define COAP_OPTION_ECHO
Definition coap_pdu.h:147
int coap_add_data(coap_pdu_t *pdu, size_t len, const uint8_t *data)
Adds given data to the pdu that is passed as first parameter.
Definition coap_pdu.c:872
coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu)
Gets the token associated with pdu.
Definition coap_pdu.c:1662
@ COAP_REQUEST_CODE_POST
Definition coap_pdu.h:334
@ COAP_REQUEST_CODE_FETCH
Definition coap_pdu.h:337
@ COAP_MESSAGE_NON
Definition coap_pdu.h:72
@ COAP_MESSAGE_ACK
Definition coap_pdu.h:73
@ COAP_MESSAGE_CON
Definition coap_pdu.h:71
coap_session_t * coap_new_client_session_pki3_lkd(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_dtls_pki_t *setup_data, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PKI credentials along with app_data infor...
coap_session_t * coap_new_client_session_psk3_lkd(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, coap_dtls_cpsk_t *setup_data, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PSK credentials along with app_data infor...
void coap_session_release_lkd(coap_session_t *session)
Decrement reference counter on a session.
coap_session_t * coap_new_client_session3_lkd(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto, void *app_data, coap_app_data_free_callback_t callback, coap_str_const_t *ws_host)
Creates a new client session to the designated server, with PSK credentials along with app_data infor...
@ COAP_OSCORE_B_2_NONE
@ COAP_OSCORE_B_2_STEP_3
@ COAP_OSCORE_B_2_STEP_1
@ COAP_OSCORE_B_2_STEP_4
@ COAP_OSCORE_B_2_STEP_5
@ COAP_OSCORE_B_2_STEP_2
#define COAP_PROTO_NOT_RELIABLE(p)
void(* coap_app_data_free_callback_t)(void *data)
Callback to free off the app data when the entry is being deleted / freed off.
void coap_delete_bin_const(coap_bin_const_t *s)
Deletes the given const binary data and releases any memory allocated.
Definition coap_str.c:130
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:81
coap_str_const_t * coap_make_str_const(const char *string)
Take the specified byte array (text) and create a coap_str_const_t *.
Definition coap_str.c:70
coap_bin_const_t * coap_new_bin_const(const uint8_t *data, size_t size)
Take the specified byte array (text) and create a coap_bin_const_t * Returns a new const binary objec...
Definition coap_str.c:119
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:114
#define coap_binary_equal(binary1, binary2)
Compares the two binary data for equality.
Definition coap_str.h:222
#define coap_string_equal(string1, string2)
Compares the two strings for equality.
Definition coap_str.h:208
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_query_into_optlist(const uint8_t *s, size_t length, coap_option_num_t optnum, coap_optlist_t **optlist_chain)
Splits the given URI query into '&' separate segments, and then adds the Uri-Query / Location-Query o...
Definition coap_uri.c:854
int coap_path_into_optlist(const uint8_t *s, size_t length, coap_option_num_t optnum, coap_optlist_t **optlist_chain)
Splits the given URI path into '/' separate segments, and then adds the Uri-Path / Location-Path opti...
Definition coap_uri.c:758
int coap_split_proxy_uri(const uint8_t *str_var, size_t len, coap_uri_t *uri)
Parses a given string into URI components.
Definition coap_uri.c:299
coap_uri_info_t coap_uri_scheme[COAP_URI_SCHEME_LAST]
Definition coap_uri.c:56
Multi-purpose address abstraction.
CoAP binary data definition with const data.
Definition coap_str.h:65
size_t length
length of binary data
Definition coap_str.h:66
const uint8_t * s
read-only binary data
Definition coap_str.h:67
CoAP binary data definition.
Definition coap_str.h:57
size_t length
length of binary data
Definition coap_str.h:58
uint8_t * s
binary data
Definition coap_str.h:59
The CoAP stack's global state is stored in a coap_context_t object.
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:414
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:316
Iterator to run through PDU options.
coap_opt_t * next_option
pointer to the unparsed next option
size_t length
remaining length of PDU
coap_option_num_t number
decoded option number
Representation of chained list of CoAP options to install.
The structure used to hold the OSCORE configuration information.
void * save_seq_num_func_param
Passed to save_seq_num_func()
uint32_t rfc8613_b_2
1 if rfc8613 B.2 protocol else 0
cose_hkdf_alg_t hkdf_alg
Set to one of COSE_HKDF_ALG_*.
uint32_t break_sender_key
1 if sender key to be broken, else 0
coap_oscore_snd_conf_t * sender
The sender - i.e.
coap_oscore_rcp_conf_t * recipient_chain
The recipients as a chain.
uint32_t ssn_freq
Sender Seq Num update frequency.
coap_oscore_save_seq_num_t save_seq_num_func
Called every seq num change.
uint32_t rfc8613_b_1_2
1 if rfc8613 B.1.2 enabled else 0
uint64_t start_seq_num
Used for ssn_freq updating.
uint32_t break_recipient_key
1 if recipient key to be broken, else 0
coap_bin_const_t * master_secret
Common Master Secret.
cose_alg_t aead_alg
Set to one of COSE_ALGORITHM_AES*.
coap_bin_const_t * master_salt
Common Master Salt.
uint32_t replay_window
Replay window size Use COAP_OSCORE_DEFAULT_REPLAY_WINDOW.
coap_bin_const_t * id_context
Common ID context.
The structure used to hold the OSCORE Recipient configuration.
coap_bin_const_t * recipient_id
Recipient ID (i.e.
struct coap_oscore_rcp_conf_t * next_recipient
Used to maintain the chain.
The structure used to hold the OSCORE Sender configuration information.
coap_bin_const_t * sender_id
Sender ID (i.e.
structure for CoAP PDUs
uint8_t max_hdr_size
space reserved for protocol-specific header
uint8_t * token
first byte of token (or extended length bytes prefix), if any, or options
coap_pdu_code_t code
request method (value 1–31) or response code (value 64-255)
coap_bin_const_t actual_token
Actual token in pdu.
uint8_t * data
first byte of payload, if any
coap_mid_t mid
message id, if any, in regular host byte order
uint32_t e_token_length
length of Token space (includes leading extended bytes
size_t used_size
used bytes of storage for token, options and payload
coap_pdu_type_t type
message type
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
uint32_t block_mode
Zero or more COAP_BLOCK_ or'd options.
coap_proto_t proto
protocol used
uint8_t con_active
Active CON request sent.
coap_context_t * context
session's context
CoAP string data definition with const data.
Definition coap_str.h:47
const uint8_t * s
read-only string data
Definition coap_str.h:49
size_t length
length of string
Definition coap_str.h:48
const char * name
scheme name
Representation of parsed URI.
Definition coap_uri.h:70
enum coap_uri_scheme_t scheme
The parsed scheme specifier.
Definition coap_uri.h:82
coap_str_const_t path
The complete path if present or {0, NULL}.
Definition coap_uri.h:73
uint16_t port
The port in host byte order.
Definition coap_uri.h:72
coap_str_const_t query
The complete query if present or {0, NULL}.
Definition coap_uri.h:77
coap_str_const_t host
The host part of the URI.
Definition coap_uri.h:71
coap_bin_const_t aad
coap_bin_const_t key
coap_bin_const_t partial_iv
coap_bin_const_t kid_context
coap_bin_const_t nonce
coap_bin_const_t external_aad
coap_bin_const_t key_id
coap_bin_const_t oscore_option
cose_alg_t alg
coap_bin_const_t * obs_partial_iv
coap_bin_const_t * partial_iv
coap_bin_const_t * aad
coap_bin_const_t * nonce
oscore_recipient_ctx_t * recipient_ctx
uint8_t rfc8613_b_1_2
1 if rfc8613 B.1.2 enabled else 0
void * save_seq_num_func_param
Passed to save_seq_num_func()
oscore_sender_ctx_t * sender_context
cose_alg_t aead_alg
Set to one of COSE_ALGORITHM_AES*.
uint8_t rfc8613_b_2
1 if rfc8613 B.2 protocol else 0
coap_oscore_save_seq_num_t save_seq_num_func
Called every seq num change.
oscore_recipient_ctx_t * recipient_chain
coap_bin_const_t * id_context
contains GID in case of group
uint32_t ssn_freq
Sender Seq Num update frequency.
coap_bin_const_t * recipient_key
coap_bin_const_t * recipient_id
coap_bin_const_t * sender_id
uint64_t seq
Sender Sequence Number.
coap_bin_const_t * sender_key
uint64_t next_seq
Used for ssn_freq updating.