libcoap 4.3.4
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 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
21#include "coap3/coap_internal.h"
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_id_count == 0) {
39 coap_log_warn("OSCORE: Recipient ID must be defined for a client\n");
40 return 0;
41 }
42 if (oscore_conf->rfc8613_b_2) {
43 /* Need to replace id_context with random value */
44 coap_binary_t *id_context = coap_new_binary(8);
45
46 if (id_context == NULL)
47 return 0;
49 coap_prng(id_context->s, id_context->length);
50 oscore_conf->id_context = (coap_bin_const_t *)id_context;
51 session->b_2_step = COAP_OSCORE_B_2_STEP_1;
52 coap_log_oscore("Appendix B.2 client step 1 (Generated ID1)\n");
53 }
54
55 osc_ctx = coap_oscore_init(session->context, oscore_conf);
56 if (osc_ctx == NULL) {
57 return 0;
58 }
59 session->recipient_ctx = osc_ctx->recipient_chain;
60 session->oscore_encryption = 1;
61 }
62 return 1;
63}
64
67 const coap_address_t *local_if,
68 const coap_address_t *server,
69 coap_proto_t proto,
70 coap_oscore_conf_t *oscore_conf) {
71 coap_session_t *session =
72 coap_new_client_session(ctx, local_if, server, proto);
73
74 if (!session)
75 return NULL;
76
77 if (coap_oscore_initiate(session, oscore_conf) == 0) {
78 coap_session_release(session);
79 return NULL;
80 }
81 return session;
82}
83
86 const coap_address_t *local_if,
87 const coap_address_t *server,
88 coap_proto_t proto,
89 coap_dtls_cpsk_t *psk_data,
90 coap_oscore_conf_t *oscore_conf) {
91 coap_session_t *session =
92 coap_new_client_session_psk2(ctx, local_if, server, proto, psk_data);
93
94 if (!session)
95 return NULL;
96
97 if (coap_oscore_initiate(session, oscore_conf) == 0) {
98 coap_session_release(session);
99 return NULL;
100 }
101 return session;
102}
103
106 const coap_address_t *local_if,
107 const coap_address_t *server,
108 coap_proto_t proto,
109 coap_dtls_pki_t *pki_data,
110 coap_oscore_conf_t *oscore_conf) {
111 coap_session_t *session =
112 coap_new_client_session_pki(ctx, local_if, server, proto, pki_data);
113
114 if (!session)
115 return NULL;
116
117 if (coap_oscore_initiate(session, oscore_conf) == 0) {
118 coap_session_release(session);
119 return NULL;
120 }
121 return session;
122}
123#endif /* COAP_CLIENT_SUPPORT */
124#if COAP_SERVER_SUPPORT
125
126int
128 coap_oscore_conf_t *oscore_conf) {
129 oscore_ctx_t *osc_ctx = coap_oscore_init(context, oscore_conf);
130
131 /* osc_ctx already added to context->osc_ctx */
132 if (osc_ctx)
133 return 1;
134 return 0;
135}
136
137#endif /* COAP_SERVER_SUPPORT */
138
139int
141 coap_uri_t uri;
142 coap_opt_iterator_t opt_iter;
143 coap_opt_t *option;
144 uint8_t option_value_buffer[15];
145 uint8_t *keep_proxy_uri = NULL;
146
147 if ((option =
148 coap_check_option(pdu, COAP_OPTION_PROXY_URI, &opt_iter)) == NULL)
149 return 1;
150
151 /* Need to break down into the component parts, but keep data safe */
152 memset(&uri, 0, sizeof(uri));
153 keep_proxy_uri = coap_malloc_type(COAP_STRING, coap_opt_length(option));
154 if (keep_proxy_uri == NULL)
155 goto error;
156 memcpy(keep_proxy_uri, coap_opt_value(option), coap_opt_length(option));
157
158 if (coap_split_proxy_uri(keep_proxy_uri,
159 coap_opt_length(option),
160 &uri) < 0 || uri.scheme >= COAP_URI_SCHEME_LAST) {
161 coap_log_warn("Proxy URI '%.*s' not decodable\n",
162 coap_opt_length(option),
163 (const char *)coap_opt_value(option));
164 goto error;
165 }
167 goto error;
168
169 if (!coap_insert_option(pdu,
171 uri.host.length,
172 uri.host.s))
173 goto error;
177 coap_encode_var_safe(option_value_buffer,
178 sizeof(option_value_buffer),
179 uri.port & 0xffff),
180 option_value_buffer))
181 goto error;
182 if (uri.path.length) {
183 uint8_t *buf;
184 uint8_t *kbuf;
185 size_t buflen = uri.path.length + 1;
186 int res;
187
188 kbuf = buf = coap_malloc_type(COAP_STRING, uri.path.length + 1);
189 if (buf) {
190 res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
191 while (res--) {
192 if (!coap_insert_option(pdu,
194 coap_opt_length(buf),
195 coap_opt_value(buf))) {
197 goto error;
198 }
199 buf += coap_opt_size(buf);
200 }
201 }
203 }
204 if (uri.query.length) {
205 uint8_t *buf;
206 size_t buflen = uri.query.length + 1;
207 int res;
208
210 if (buf) {
211 res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
212 while (res--) {
213 if (!coap_insert_option(pdu,
215 coap_opt_length(buf),
216 coap_opt_value(buf))) {
218 goto error;
219 }
220
221 buf += coap_opt_size(buf);
222 }
224 }
225 }
226 if (!coap_insert_option(pdu,
228 strlen(coap_uri_scheme[uri.scheme].name),
229 (const uint8_t *)coap_uri_scheme[uri.scheme].name))
230 goto error;
231 coap_free_type(COAP_STRING, keep_proxy_uri);
232 return 1;
233
234error:
235 coap_free_type(COAP_STRING, keep_proxy_uri);
236 return 0;
237}
238
239static void
240dump_cose(cose_encrypt0_t *cose, const char *message) {
241#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_OSCORE
242 (void)cose;
243 (void)message;
244#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_OSCORE */
246 char buffer[30];
247
248 coap_log_oscore("%s Cose information\n", message);
250 cose_get_alg_name(cose->alg, buffer, sizeof(buffer)));
252 oscore_log_hex_value(COAP_LOG_OSCORE, "partial_iv", &cose->partial_iv);
254 oscore_log_hex_value(COAP_LOG_OSCORE, "kid_context", &cose->kid_context);
256 "oscore_option",
257 &cose->oscore_option);
259 oscore_log_hex_value(COAP_LOG_OSCORE, "external_aad", &cose->external_aad);
261 }
262#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_OSCORE */
263}
264
265/*
266 * Take current PDU, create a new one approriately separated as per RFC8613
267 * and then encrypt / integrity check the OSCORE data
268 */
271 coap_pdu_t *pdu,
272 coap_bin_const_t *kid_context,
273 oscore_partial_iv_t send_partial_iv) {
274 uint8_t coap_request = COAP_PDU_IS_REQUEST(pdu);
275 coap_pdu_code_t code =
276 coap_request ? COAP_REQUEST_CODE_POST : COAP_RESPONSE_CODE(204);
277 coap_pdu_t *osc_pdu;
278 coap_pdu_t *plain_pdu = NULL;
279 coap_bin_const_t pdu_token;
280 coap_opt_iterator_t opt_iter;
281 coap_opt_t *option;
282 uint8_t pdu_code = pdu->code;
283 size_t length;
284 const uint8_t *data;
285 uint8_t *ciphertext_buffer = NULL;
286 size_t ciphertext_len = 0;
287 uint8_t aad_buffer[AAD_BUF_LEN];
288 uint8_t nonce_buffer[13];
290 coap_bin_const_t nonce;
291 oscore_recipient_ctx_t *rcp_ctx = session->recipient_ctx;
292 oscore_ctx_t *osc_ctx = rcp_ctx ? rcp_ctx->osc_ctx : NULL;
293 cose_encrypt0_t cose[1];
294 uint8_t group_flag = 0;
295 int show_pdu = 0;
296 int doing_observe = 0;
297 uint32_t observe_value = 0;
298 oscore_association_t *association = NULL;
299 oscore_sender_ctx_t *snd_ctx = osc_ctx ? osc_ctx->sender_context : NULL;
300 uint8_t external_aad_buffer[200];
301 coap_bin_const_t external_aad;
302 uint8_t oscore_option[48];
303 size_t oscore_option_len;
304
305 /* Check that OSCORE has not already been done */
306 if (coap_check_option(pdu, COAP_OPTION_OSCORE, &opt_iter))
307 return NULL;
308
309 if (coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter))
310 doing_observe = 1;
311
312 coap_log_debug("PDU to encrypt\n");
314 osc_pdu = coap_pdu_init(pdu->type == COAP_MESSAGE_NON &&
315 session->b_2_step != COAP_OSCORE_B_2_NONE ?
316 COAP_MESSAGE_CON : pdu->type,
317 code,
318 pdu->mid,
319 pdu->used_size + coap_oscore_overhead(session, pdu));
320 if (osc_pdu == NULL)
321 return NULL;
322
323 cose_encrypt0_init(cose); /* clears cose memory */
324 pdu_token = coap_pdu_get_token(pdu);
325 if (coap_request) {
326 /*
327 * RFC8613 8.1 Step 1. Protecting the client's request
328 * Get the Sender Context
329 */
330 rcp_ctx = session->recipient_ctx;
331 if (rcp_ctx == NULL)
332 goto error;
333 osc_ctx = rcp_ctx->osc_ctx;
334 snd_ctx = osc_ctx->sender_context;
335 } else {
336 /*
337 * RFC8613 8.3 Step 1. Protecting the server's response
338 * Get the Sender Context
339 */
340 association = oscore_find_association(session, &pdu_token);
341 if (association == NULL)
342 goto error;
343
344 rcp_ctx = association->recipient_ctx;
345 osc_ctx = rcp_ctx->osc_ctx;
346 snd_ctx = osc_ctx->sender_context;
347 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
348 cose_encrypt0_set_aad(cose, association->aad);
349 }
350
351 cose_encrypt0_set_alg(cose, osc_ctx->aead_alg);
352
353 if (coap_request || doing_observe ||
354 send_partial_iv == OSCORE_SEND_PARTIAL_IV) {
355 uint8_t partial_iv_buffer[8];
356 size_t partial_iv_len;
357 coap_bin_const_t partial_iv;
358 partial_iv_len = coap_encode_var_safe8(partial_iv_buffer,
359 sizeof(partial_iv_buffer),
360 snd_ctx->seq);
361 if (snd_ctx->seq == 0) {
362 /* Need to special case */
363 partial_iv_buffer[0] = '\000';
364 partial_iv_len = 1;
365 }
366 partial_iv.s = partial_iv_buffer;
367 partial_iv.length = partial_iv_len;
368 cose_encrypt0_set_partial_iv(cose, &partial_iv);
369 }
370
371 if (coap_request)
373
374 cose_encrypt0_set_key_id(cose, snd_ctx->sender_id);
375
376 /* nonce (needs to have sender information correctly set up) */
377
378 if (coap_request || doing_observe ||
379 send_partial_iv == OSCORE_SEND_PARTIAL_IV) {
380 /*
381 * 8.1 Step 3 or RFC8613 8.3.1 Step A
382 * Compose the AEAD nonce
383 *
384 * Requires in COSE object as appropriate
385 * key_id (kid) (sender)
386 * partial_iv (sender)
387 * common_iv (already in osc_ctx)
388 */
389 nonce.s = nonce_buffer;
390 nonce.length = 13;
391 oscore_generate_nonce(cose, osc_ctx, nonce_buffer, 13);
392 cose_encrypt0_set_nonce(cose, &nonce);
393 if (!oscore_increment_sender_seq(osc_ctx))
394 goto error;
395 if (osc_ctx->save_seq_num_func) {
396 if (osc_ctx->sender_context->seq > osc_ctx->sender_context->next_seq) {
397 /* Only update at ssn_freq rate */
398 osc_ctx->sender_context->next_seq += osc_ctx->ssn_freq;
399 osc_ctx->save_seq_num_func(osc_ctx->sender_context->next_seq,
400 osc_ctx->save_seq_num_func_param);
401 }
402 }
403 } else {
404 /*
405 * 8.3 Step 3.
406 * Use nonce from request
407 */
408 cose_encrypt0_set_nonce(cose, association->nonce);
409 }
410
411 /* OSCORE_option (needs to be before AAD as included in AAD if group) */
412
413 /* cose is modified for encode option in response message */
414 if (!coap_request) {
415 /* no kid on response */
416 cose_encrypt0_set_key_id(cose, NULL);
417 if (!doing_observe && send_partial_iv == OSCORE_SEND_NO_IV)
419 }
420 if (kid_context) {
421 cose_encrypt0_set_kid_context(cose, kid_context);
422 }
423 oscore_option_len =
424 oscore_encode_option_value(oscore_option, sizeof(oscore_option), cose,
425 group_flag,
426 session->b_2_step != COAP_OSCORE_B_2_NONE);
427 if (!coap_request) {
428 /* Reset what was just unset as appropriate for AAD */
430 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
431 }
432 if (kid_context)
434
435 /*
436 * RFC8613 8.1/8.3 Step 2(a) (5.4).
437 * Compose the External AAD and then AAD
438 *
439 * OSCORE_option requires
440 * partial_iv (cose partial_iv)
441 * kid_context (cose kid_context)
442 * key_id (cose key_id)
443 * group_flag
444 *
445 * Non Group (based on osc_tx->mode) requires the following
446 * aead_alg (osc_ctx)
447 * request_kid (request key_id using cose)
448 * request_piv (request partial_iv using cose)
449 * options (none at present)
450 * Group (based on osc_tx->mode) requires the following
451 * aead_alg (osc_ctx) (pairwise mode)
452 * sign_enc_alg (osc_ctx) (group mode)
453 * sign_alg (osc_ctx) (group mode)
454 * alg_pairwise_key_agreement (osc_ctx) (pairwise mode)
455 * request_kid (request key_id using cose)
456 * request_piv (request partial_iv using cose)
457 * options (none at present)
458 * request_kid_context (osc_ctx id_context)
459 * OSCORE_option (parameter)
460 * test_gs_public_key (osc_ctx sender_context public_key)
461 * gm_public_key (osc_ctx gm_public_key)
462 *
463 * Note: No I options at present
464 */
465 if (coap_request || osc_ctx->mode != OSCORE_MODE_SINGLE ||
466 send_partial_iv == OSCORE_SEND_PARTIAL_IV) {
467 /* External AAD */
468 external_aad.s = external_aad_buffer;
469 external_aad.length = oscore_prepare_e_aad(osc_ctx,
470 cose,
471 NULL,
472 0,
473 NULL,
474 external_aad_buffer,
475 sizeof(external_aad_buffer));
476 cose_encrypt0_set_external_aad(cose, &external_aad);
477
478 /* AAD */
479 aad.s = aad_buffer;
480 aad.length = oscore_prepare_aad(external_aad_buffer,
481 external_aad.length,
482 aad_buffer,
483 sizeof(aad_buffer));
484 assert(aad.length < AAD_BUF_LEN);
485 cose_encrypt0_set_aad(cose, &aad);
486 }
487
488 /*
489 * RFC8613 8.1/8.3 Step 2(b) (5.3).
490 *
491 * Set up temp plaintext pdu, the data including token, options and
492 * optional payload will get encrypted as COSE ciphertext.
493 */
494 plain_pdu = coap_pdu_init(pdu->type,
495 pdu->code,
496 pdu->mid,
497 pdu->used_size);
498 if (plain_pdu == NULL)
499 goto error;
500
501 coap_add_token(osc_pdu, pdu_token.length, pdu_token.s);
502
503 /* First byte of plain is real CoAP code. Pretend it is token */
504 coap_add_token(plain_pdu, 1, &pdu_code);
505
506 /* Copy across the Outer/Inner Options to respective PDUs */
508 while ((option = coap_option_next(&opt_iter))) {
509 switch (opt_iter.number) {
514 /* Outer only */
515 if (!coap_insert_option(osc_pdu,
516 opt_iter.number,
517 coap_opt_length(option),
518 coap_opt_value(option)))
519 goto error;
520 break;
522 /* Make as Outer option as-is */
523 if (!coap_insert_option(osc_pdu,
524 opt_iter.number,
525 coap_opt_length(option),
526 coap_opt_value(option)))
527 goto error;
528 if (coap_request) {
529 /* Make as Inner option (unchanged) */
530 if (!coap_insert_option(plain_pdu,
531 opt_iter.number,
532 coap_opt_length(option),
533 coap_opt_value(option)))
534 goto error;
535 osc_pdu->code = COAP_REQUEST_CODE_FETCH;
536 } else {
537 /* Make as Inner option but empty */
538 if (!coap_insert_option(plain_pdu, opt_iter.number, 0, NULL))
539 goto error;
540 osc_pdu->code = COAP_RESPONSE_CODE(205);
541 }
542 show_pdu = 1;
543 doing_observe = 1;
544 observe_value = coap_decode_var_bytes(coap_opt_value(option),
545 coap_opt_length(option));
546 break;
548 /*
549 * Should have already been caught by doing
550 * coap_rebuild_pdu_for_proxy() before calling
551 * coap_oscore_new_pdu_encrypted()
552 */
553 assert(0);
554 break;
555 default:
556 /* Make as Inner option */
557 if (!coap_insert_option(plain_pdu,
558 opt_iter.number,
559 coap_opt_length(option),
560 coap_opt_value(option)))
561 goto error;
562 break;
563 }
564 }
565 /* Add in data to plain */
566 if (coap_get_data(pdu, &length, &data)) {
567 if (!coap_add_data(plain_pdu, length, data))
568 goto error;
569 }
570 if (show_pdu) {
571 coap_log_oscore("OSCORE payload\n");
572 coap_show_pdu(COAP_LOG_OSCORE, plain_pdu);
573 }
574
575 /*
576 * 8.1/8.3 Step 4.
577 * Encrypt the COSE object.
578 *
579 * Requires in COSE object as appropriate
580 * alg (already set)
581 * key (sender key)
582 * nonce (already set)
583 * aad (already set)
584 * plaintext
585 */
586 cose_encrypt0_set_key(cose, snd_ctx->sender_key);
587 cose_encrypt0_set_plaintext(cose, plain_pdu->token, plain_pdu->used_size);
588 dump_cose(cose, "Pre encrypt");
589 ciphertext_buffer =
590 coap_malloc_type(COAP_OSCORE_BUF, OSCORE_CRYPTO_BUFFER_SIZE);
591 if (ciphertext_buffer == NULL)
592 goto error;
593 ciphertext_len = cose_encrypt0_encrypt(cose,
594 ciphertext_buffer,
595 plain_pdu->used_size + AES_CCM_TAG);
596 if ((int)ciphertext_len <= 0) {
597 coap_log_warn("OSCORE: Encryption Failure, result code: %d \n",
598 (int)ciphertext_len);
599 goto error;
600 }
601 assert(ciphertext_len < OSCORE_CRYPTO_BUFFER_SIZE);
602
603 /* Add in OSCORE option (previously computed) */
604 if (!coap_insert_option(osc_pdu,
606 oscore_option_len,
607 oscore_option))
608 goto error;
609
610 /* Add now encrypted payload */
611 if (!coap_add_data(osc_pdu, ciphertext_len, ciphertext_buffer))
612 goto error;
613
614 coap_free_type(COAP_OSCORE_BUF, ciphertext_buffer);
615 ciphertext_buffer = NULL;
616
617 coap_delete_pdu(plain_pdu);
618 plain_pdu = NULL;
619
620 if (association && association->is_observe == 0)
621 oscore_delete_association(session, association);
622 association = NULL;
623
624 /*
625 * If this is a response ACK with data, make it a separate response
626 * by sending an Empty ACK and changing osc_pdu's MID and type. This
627 * then allows lost response ACK with data to be recovered.
628 */
629 if (coap_request == 0 && osc_pdu->type == COAP_MESSAGE_ACK &&
630 COAP_PROTO_NOT_RELIABLE(session->proto)) {
632 0,
633 osc_pdu->mid,
634 0);
635 if (empty) {
636 if (coap_send_internal(session, empty) != COAP_INVALID_MID) {
637 osc_pdu->mid = coap_new_message_id(session);
638 osc_pdu->type = COAP_MESSAGE_CON;
639 }
640 }
641 }
642
643 if (!coap_pdu_encode_header(osc_pdu, session->proto)) {
644 goto error;
645 }
646
647 /*
648 * Set up an association for handling a response if this is a request
649 */
650 if (coap_request) {
651 association = oscore_find_association(session, &pdu_token);
652 if (association) {
653 if (doing_observe && observe_value == 1) {
654 association->is_observe = 0;
655 }
656 /* Refresh the association */
657 coap_delete_bin_const(association->nonce);
658 association->nonce =
659 coap_new_bin_const(cose->nonce.s, cose->nonce.length);
660 if (association->nonce == NULL)
661 goto error;
662 coap_delete_bin_const(association->aad);
663 association->aad = coap_new_bin_const(cose->aad.s, cose->aad.length);
664 if (association->aad == NULL)
665 goto error;
666 coap_delete_bin_const(association->partial_iv);
667 association->partial_iv =
669 if (association->partial_iv == NULL)
670 goto error;
671 association->recipient_ctx = rcp_ctx;
672 coap_delete_pdu(association->sent_pdu);
673 if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
674 size_t size;
675
676 association->sent_pdu = coap_pdu_duplicate(pdu, session,
677 pdu_token.length,
678 pdu_token.s, NULL);
679 if (association->sent_pdu == NULL)
680 goto error;
681 if (coap_get_data(pdu, &size, &data)) {
682 coap_add_data(association->sent_pdu, size, data);
683 }
684 } else {
685 association->sent_pdu = NULL;
686 }
687 } else if (!oscore_new_association(session,
688 session->b_2_step != COAP_OSCORE_B_2_NONE ? pdu : NULL,
689 &pdu_token,
690 rcp_ctx,
691 &cose->aad,
692 &cose->nonce,
693 &cose->partial_iv,
694 doing_observe)) {
695 goto error;
696 }
697 }
698 return osc_pdu;
699
700error:
701 if (ciphertext_buffer)
702 coap_free_type(COAP_OSCORE_BUF, ciphertext_buffer);
703 coap_delete_pdu(osc_pdu);
704 coap_delete_pdu(plain_pdu);
705 return NULL;
706}
707
708static void
709build_and_send_error_pdu(coap_session_t *session,
710 coap_pdu_t *rcvd,
711 coap_pdu_code_t code,
712 const char *diagnostic,
713 uint8_t *echo_data,
714 coap_bin_const_t *kid_context,
715 int encrypt_oscore) {
716 coap_pdu_t *err_pdu = NULL;
717 coap_bin_const_t token;
718 int oscore_encryption = session->oscore_encryption;
719 unsigned char buf[4];
720
721 token = coap_pdu_get_token(rcvd);
724 code,
725 rcvd->mid,
726 token.length + 2 + 8 +
727 (diagnostic ? strlen(diagnostic) : 0));
728 if (!err_pdu)
729 return;
730 coap_add_token(err_pdu, token.length, token.s);
731 if (echo_data) {
732 coap_add_option_internal(err_pdu, COAP_OPTION_ECHO, 8, echo_data);
733 } else if (kid_context == NULL) {
736 coap_encode_var_safe(buf, sizeof(buf), 0),
737 buf);
738 }
739 if (diagnostic)
740 coap_add_data(err_pdu, strlen(diagnostic), (const uint8_t *)diagnostic);
741 session->oscore_encryption = encrypt_oscore;
742
743 if ((echo_data || kid_context) && encrypt_oscore) {
744 coap_pdu_t *osc_pdu;
745
746 osc_pdu =
747 coap_oscore_new_pdu_encrypted(session, err_pdu, kid_context,
748 echo_data ? 1 : 0);
749 if (!osc_pdu)
750 goto fail_resp;
751 session->oscore_encryption = 0;
752 coap_send_internal(session, osc_pdu);
753 coap_delete_pdu(err_pdu);
754 err_pdu = NULL;
755 } else {
756 coap_send_internal(session, err_pdu);
757 err_pdu = NULL;
758 }
759fail_resp:
760 session->oscore_encryption = oscore_encryption;
761 coap_delete_pdu(err_pdu);
762 return;
763}
764
765/* pdu contains incoming message with encrypted COSE ciphertext payload
766 * function returns decrypted message
767 * and verifies signature, if present
768 * returns NULL when decryption,verification fails
769 */
772 coap_pdu_t *pdu) {
773 coap_pdu_t *decrypt_pdu = NULL;
774 coap_pdu_t *plain_pdu = NULL;
775 const uint8_t *osc_value; /* value of OSCORE option */
776 uint8_t osc_size; /* size of OSCORE OPTION */
777 coap_opt_iterator_t opt_iter;
778 coap_opt_t *opt = NULL;
779 cose_encrypt0_t cose[1];
780 oscore_ctx_t *osc_ctx = NULL;
781 uint8_t aad_buffer[AAD_BUF_LEN];
782 uint8_t nonce_buffer[13];
784 coap_bin_const_t nonce;
785 int pltxt_size = 0;
786 uint8_t coap_request = COAP_PDU_IS_REQUEST(pdu);
787 coap_bin_const_t pdu_token;
788 uint8_t *st_encrypt;
789 size_t encrypt_len;
790 size_t tag_len;
791 oscore_recipient_ctx_t *rcp_ctx = NULL;
792 oscore_association_t *association = NULL;
793 uint8_t external_aad_buffer[100];
794 coap_bin_const_t external_aad;
795 oscore_sender_ctx_t *snd_ctx = NULL;
796#if COAP_CLIENT_SUPPORT
797 coap_pdu_t *sent_pdu = NULL;
798#endif /* COAP_CLIENT_SUPPORT */
799
800 opt = coap_check_option(pdu, COAP_OPTION_OSCORE, &opt_iter);
801 assert(opt);
802 if (opt == NULL)
803 return NULL;
804
805 if (session->context->p_osc_ctx == NULL) {
806 coap_log_warn("OSCORE: Not enabled\n");
807 if (!coap_request)
808 coap_handle_event(session->context,
810 session);
811 return NULL;
812 }
813
814 if (pdu->data == NULL) {
815 coap_log_warn("OSCORE: No protected payload\n");
816 if (!coap_request)
817 coap_handle_event(session->context,
819 session);
820 return NULL;
821 }
822
823 osc_size = coap_opt_length(opt);
824 osc_value = coap_opt_value(opt);
825
826 cose_encrypt0_init(cose); /* clear cose memory */
827
828 /* PDU code will be filled in after decryption */
829 decrypt_pdu =
830 coap_pdu_init(pdu->type, 0, pdu->mid, pdu->used_size);
831 if (decrypt_pdu == NULL) {
832 if (!coap_request)
833 coap_handle_event(session->context,
835 session);
836 goto error;
837 }
838
839 /* Copy across the Token */
840 pdu_token = coap_pdu_get_token(pdu);
841 coap_add_token(decrypt_pdu, pdu_token.length, pdu_token.s);
842
843 /*
844 * 8.2/8.4 Step 1.
845 * Copy outer options across, except E and OSCORE options
846 */
848 while ((opt = coap_option_next(&opt_iter))) {
849 switch (opt_iter.number) {
850 /* 'E' options skipped */
852 case COAP_OPTION_ETAG:
867 case COAP_OPTION_ECHO:
868 case COAP_OPTION_RTAG:
869 /* OSCORE does not get copied across */
871 break;
872 default:
873 if (!coap_add_option_internal(decrypt_pdu,
874 opt_iter.number,
875 coap_opt_length(opt),
876 coap_opt_value(opt))) {
877 if (!coap_request)
878 coap_handle_event(session->context,
880 session);
881 goto error;
882 }
883 break;
884 }
885 }
886
887 if (coap_request) {
888 uint64_t incoming_seq;
889 /*
890 * 8.2 Step 2
891 * Decompress COSE object
892 * Get Recipient Context based on kid and optional kid_context
893 */
894 if (oscore_decode_option_value(osc_value, osc_size, cose) == 0) {
895 coap_log_warn("OSCORE: OSCORE Option cannot be decoded.\n");
896 build_and_send_error_pdu(session,
897 pdu,
899 "Failed to decode COSE",
900 NULL,
901 NULL,
902 0);
903 goto error_no_ack;
904 }
905 osc_ctx = oscore_find_context(session->context,
906 cose->key_id,
907 &cose->kid_context,
908 NULL,
909 &rcp_ctx);
910 if (!osc_ctx) {
911 if (cose->kid_context.length > 0) {
912 const uint8_t *ptr;
913 size_t length;
914 /* Appendix B.2 protocol check - Is the recipient key_id known */
915 osc_ctx = oscore_find_context(session->context,
916 cose->key_id,
917 NULL,
918 session->oscore_r2 != 0 ? (uint8_t *)&session->oscore_r2 : NULL,
919 &rcp_ctx);
920 ptr = cose->kid_context.s;
921 length = cose->kid_context.length;
922 if (ptr && osc_ctx && osc_ctx->rfc8613_b_2 &&
923 osc_ctx->mode == OSCORE_MODE_SINGLE) {
924 /* Processing Appendix B.2 protocol */
925 /* Need to CBOR unwrap kid_context */
926 coap_bin_const_t kid_context;
927
928 kid_context.length = oscore_cbor_get_element_size(&ptr, &length);
929 kid_context.s = ptr;
930 cose_encrypt0_set_kid_context(cose, (coap_bin_const_t *)&kid_context);
931
932 if (session->oscore_r2 != 0) {
933 /* B.2 step 4 */
935 cose->kid_context.length);
936
937 if (kc == NULL)
938 goto error;
939
940 session->b_2_step = COAP_OSCORE_B_2_STEP_4;
941 coap_log_oscore("Appendix B.2 server step 4 (R2 || R3)\n");
942 oscore_update_ctx(osc_ctx, kc);
943 } else {
944 session->b_2_step = COAP_OSCORE_B_2_STEP_2;
945 coap_log_oscore("Appendix B.2 server step 2 (ID1)\n");
946 osc_ctx = oscore_duplicate_ctx(session->context,
947 osc_ctx,
948 osc_ctx->sender_context->sender_id,
949 &cose->key_id,
950 &cose->kid_context);
951 if (osc_ctx == NULL)
952 goto error;
953 /*
954 * Complete the Verify (B.2 step 2)
955 * before sending back the response
956 */
957 rcp_ctx = osc_ctx->recipient_chain;
958 }
959 } else {
960 osc_ctx = NULL;
961 }
962 }
963 } else if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
964 session->b_2_step = COAP_OSCORE_B_2_NONE;
965 coap_log_oscore("Appendix B.2 server finished\n");
966 }
967 if (!osc_ctx) {
968 coap_log_crit("OSCORE: Security Context not found\n");
970 oscore_log_hex_value(COAP_LOG_OSCORE, "kid_context", &cose->kid_context);
971 build_and_send_error_pdu(session,
972 pdu,
974 "Security context not found",
975 NULL,
976 NULL,
977 0);
978 goto error_no_ack;
979 }
980 /* to be used for encryption of returned response later */
981 session->recipient_ctx = rcp_ctx;
982 snd_ctx = osc_ctx->sender_context;
983
984 /*
985 * 8.2 Step 3.
986 * Verify Partial IV is not duplicated.
987 *
988 * Requires in COSE object as appropriate
989 * partial_iv (as received)
990 */
991 if (rcp_ctx->initial_state == 0 &&
992 !oscore_validate_sender_seq(rcp_ctx, cose)) {
993 coap_log_warn("OSCORE: Replayed or old message\n");
994 build_and_send_error_pdu(session,
995 pdu,
997 "Replay detected",
998 NULL,
999 NULL,
1000 0);
1001 goto error_no_ack;
1002 }
1003
1004 incoming_seq =
1006 rcp_ctx->last_seq = incoming_seq;
1007 } else { /* !coap_request */
1008 /*
1009 * 8.4 Step 2
1010 * Decompress COSE object
1011 * Get Recipient Context based on token
1012 */
1013 if (oscore_decode_option_value(osc_value, osc_size, cose) == 0) {
1014 coap_log_warn("OSCORE: OSCORE Option cannot be decoded.\n");
1015 coap_handle_event(session->context,
1017 session);
1018 goto error;
1019 }
1020 association = oscore_find_association(session, &pdu_token);
1021 if (association) {
1022 rcp_ctx = association->recipient_ctx;
1023 osc_ctx = rcp_ctx->osc_ctx;
1024 snd_ctx = osc_ctx->sender_context;
1025#if COAP_CLIENT_SUPPORT
1026 sent_pdu = association->sent_pdu;
1027 if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
1028 const uint8_t *ptr = cose->kid_context.s;
1029 size_t length = cose->kid_context.length;
1030
1031 if (ptr) {
1032 /* Need to CBOR unwrap kid_context */
1033 coap_bin_const_t kid_context;
1034
1035 kid_context.length = oscore_cbor_get_element_size(&ptr, &length);
1036 kid_context.s = ptr;
1037 cose_encrypt0_set_kid_context(cose, &kid_context);
1038 }
1039 if (ptr && !coap_binary_equal(osc_ctx->id_context, &cose->kid_context)) {
1040 /* If Appendix B.2 step 3 is in operation */
1041 /* Need to update Security Context with new (R2 || ID1) ID Context */
1043 osc_ctx->id_context->length);
1044
1045 if (kc == NULL) {
1046 coap_handle_event(session->context,
1048 session);
1049 goto error;
1050 }
1051
1052 memcpy(kc->s, cose->kid_context.s, cose->kid_context.length);
1053 memcpy(&kc->s[cose->kid_context.length],
1054 osc_ctx->id_context->s,
1055 osc_ctx->id_context->length);
1056
1057 session->b_2_step = COAP_OSCORE_B_2_STEP_3;
1058 coap_log_oscore("Appendix B.2 client step 3 (R2 || ID1)\n");
1059 oscore_update_ctx(osc_ctx, (coap_bin_const_t *)kc);
1060 } else {
1061 session->b_2_step = COAP_OSCORE_B_2_STEP_5;
1062 coap_log_oscore("Appendix B.2 client step 5 (R2 || R3)\n");
1063 }
1064 }
1065#endif /* COAP_CLIENT_SUPPORT */
1066 } else {
1067 coap_log_crit("OSCORE: Security Context association not found\n");
1068 coap_handle_event(session->context,
1070 session);
1071 goto error;
1072 }
1073 }
1074
1075 cose_encrypt0_set_alg(cose, osc_ctx->aead_alg);
1076
1077 if (coap_request) {
1078 /*
1079 * RFC8613 8.2 Step 4.
1080 * Compose the External AAD and then AAD
1081 *
1082 * Non Group (based on osc_tx->mode) requires the following
1083 * aead_alg (osc_ctx)
1084 * request_kid (request key_id using cose)
1085 * request_piv (request partial_iv using cose)
1086 * options (none at present)
1087 * Group (based on osc_tx->mode) requires the following
1088 * aead_alg (osc_ctx) (pairwise mode)
1089 * sign_enc_alg (osc_ctx) (group mode)
1090 * sign_alg (osc_ctx) (group mode)
1091 * alg_pairwise_key_agreement (osc_ctx) (pairwise mode)
1092 * request_kid (request key_id using cose)
1093 * request_piv (request partial_iv using cose)
1094 * options (none at present)
1095 * request_kid_context (osc_ctx id_context)
1096 * OSCORE_option (as received in request)
1097 * test_gs_public_key (recipient public key)
1098 * gm_public_key (osc_ctx gm_public_key)
1099 *
1100 * Note: No I options at present
1101 */
1102
1103 /* External AAD */
1104 external_aad.s = external_aad_buffer;
1105 external_aad.length = oscore_prepare_e_aad(osc_ctx,
1106 cose,
1107 osc_value,
1108 osc_size,
1109 NULL,
1110 external_aad_buffer,
1111 sizeof(external_aad_buffer));
1112 cose_encrypt0_set_external_aad(cose, &external_aad);
1113
1114 /* AAD */
1115 aad.s = aad_buffer;
1116 aad.length = oscore_prepare_aad(external_aad_buffer,
1117 external_aad.length,
1118 aad_buffer,
1119 sizeof(aad_buffer));
1120 assert(aad.length < AAD_BUF_LEN);
1121 cose_encrypt0_set_aad(cose, &aad);
1122
1123 /*
1124 * RFC8613 8.2 Step 5.
1125 * Compute the AEAD nonce.
1126 *
1127 * Requires in COSE object as appropriate
1128 * key_id (kid) (Recipient ID)
1129 * partial_iv (as received in request)
1130 * common_iv (already in osc_ctx)
1131 */
1132 nonce.s = nonce_buffer;
1133 nonce.length = 13;
1134 oscore_generate_nonce(cose, osc_ctx, nonce_buffer, 13);
1135 cose_encrypt0_set_nonce(cose, &nonce);
1136 /*
1137 * Set up an association for use in the response
1138 */
1139 association = oscore_find_association(session, &pdu_token);
1140 if (association) {
1141 /* Refresh the association */
1142 coap_delete_bin_const(association->nonce);
1143 association->nonce =
1144 coap_new_bin_const(cose->nonce.s, cose->nonce.length);
1145 if (association->nonce == NULL)
1146 goto error;
1147 coap_delete_bin_const(association->partial_iv);
1148 association->partial_iv =
1150 if (association->partial_iv == NULL)
1151 goto error;
1152 coap_delete_bin_const(association->aad);
1153 association->aad = coap_new_bin_const(cose->aad.s, cose->aad.length);
1154 if (association->aad == NULL)
1155 goto error;
1156 association->recipient_ctx = rcp_ctx;
1157 } else if (!oscore_new_association(session,
1158 NULL,
1159 &pdu_token,
1160 rcp_ctx,
1161 &cose->aad,
1162 &cose->nonce,
1163 &cose->partial_iv,
1164 0)) {
1165 goto error;
1166 }
1167 /* So association is not released when handling decrypt */
1168 association = NULL;
1169 } else { /* ! coap_request */
1170 /* Need to do nonce before AAD because of different partial_iv */
1171 /*
1172 * 8.4 Step 4.
1173 * Compose the AEAD nonce.
1174 */
1175 cose_encrypt0_set_key_id(cose, rcp_ctx->recipient_id);
1176 if (cose->partial_iv.length == 0) {
1177 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
1178 cose_encrypt0_set_nonce(cose, association->nonce);
1179 } else {
1180 uint64_t last_seq;
1181
1182 if (rcp_ctx->initial_state == 0 &&
1183 !oscore_validate_sender_seq(rcp_ctx, cose)) {
1184 coap_log_warn("OSCORE: Replayed or old message\n");
1185 goto error;
1186 }
1187 last_seq =
1189 if (rcp_ctx->last_seq>= OSCORE_SEQ_MAX) {
1190 coap_log_warn("OSCORE Replay protection, SEQ larger than SEQ_MAX.\n");
1191 goto error;
1192 }
1193 if (last_seq > rcp_ctx->last_seq)
1194 rcp_ctx->last_seq = last_seq;
1195 /*
1196 * Requires in COSE object as appropriate
1197 * kid (set above)
1198 * partial_iv (as received)
1199 * common_iv (already in osc_ctx)
1200 */
1201 oscore_generate_nonce(cose, osc_ctx, nonce_buffer, 13);
1202 nonce.s = nonce_buffer;
1203 nonce.length = 13;
1204 cose_encrypt0_set_nonce(cose, &nonce);
1205 }
1206#ifdef OSCORE_EXTRA_DEBUG
1207 dump_cose(cose, "!req post set nonce");
1208#endif /* OSCORE_EXTRA_DEBUG */
1209 /*
1210 * 8.4 Step 3.
1211 * Compose the External AAD and then AAD (same as request non-group (5.4)
1212 *
1213 * Non Group (based on osc_tx->mode) requires the following
1214 * aead_alg (osc_ctx)
1215 * request_kid (request key_id using cose)
1216 * request_piv (request partial_iv using cose)
1217 * options (none at present)
1218 * Group (based on osc_tx->mode) requires the following
1219 * aead_alg (osc_ctx) (pairwise mode)
1220 * sign_enc_alg (osc_ctx) (group mode)
1221 * sign_alg (osc_ctx) (group mode)
1222 * alg_pairwise_key_agreement (osc_ctx) (pairwise mode)
1223 * request_kid (request key_id using cose)
1224 * request_piv (request partial_iv using cose)
1225 * options (none at present)
1226 * request_kid_context (osc_ctx id_context)
1227 * OSCORE_option (as received in request)
1228 * test_gs_public_key (recipient public key)
1229 * gm_public_key (osc_ctx gm_public_key)
1230 *
1231 * Note: No I options at present
1232 */
1233
1234 /* External AAD */
1235 cose_encrypt0_set_key_id(cose, snd_ctx->sender_id);
1236 cose_encrypt0_set_partial_iv(cose, association->partial_iv);
1237#ifdef OSCORE_EXTRA_DEBUG
1238 dump_cose(cose, "!req pre aad");
1239#endif /* OSCORE_EXTRA_DEBUG */
1240 external_aad.s = external_aad_buffer;
1241 external_aad.length = oscore_prepare_e_aad(osc_ctx,
1242 cose,
1243 NULL,
1244 0,
1245 NULL,
1246 external_aad_buffer,
1247 sizeof(external_aad_buffer));
1248 cose_encrypt0_set_external_aad(cose, &external_aad);
1249
1250 /* AAD */
1251 aad.s = aad_buffer;
1252 aad.length = oscore_prepare_aad(external_aad_buffer,
1253 external_aad.length,
1254 aad_buffer,
1255 sizeof(aad_buffer));
1256 assert(aad.length < AAD_BUF_LEN);
1257 cose_encrypt0_set_aad(cose, &aad);
1258#ifdef OSCORE_EXTRA_DEBUG
1259 dump_cose(cose, "!req post set aad");
1260#endif /* OSCORE_EXTRA_DEBUG */
1261 }
1262
1263 /*
1264 * 8.2 Step 6 / 8.4 Step 5.
1265 * Decrypt the COSE object.
1266 *
1267 * Requires in COSE object as appropriate
1268 * alg (already set)
1269 * key
1270 * nonce (already set)
1271 * aad (already set)
1272 * ciphertext
1273 */
1274 st_encrypt = pdu->data;
1275 encrypt_len = pdu->used_size - (pdu->data - pdu->token);
1276 if (encrypt_len <= 0) {
1277 coap_log_warn("OSCORE: No protected payload\n");
1278 if (!coap_request)
1279 coap_handle_event(session->context,
1281 session);
1282 goto error;
1283 }
1284 cose_encrypt0_set_key(cose, rcp_ctx->recipient_key);
1285 cose_encrypt0_set_ciphertext(cose, st_encrypt, encrypt_len);
1286
1287 tag_len = cose_tag_len(cose->alg);
1288 /* Decrypt into plain_pdu, so code (token), options and data are in place */
1289 plain_pdu = coap_pdu_init(0, 0, 0, encrypt_len /* - tag_len */);
1290 if (plain_pdu == NULL) {
1291 if (!coap_request)
1292 coap_handle_event(session->context,
1294 session);
1295 goto error;
1296 }
1297
1298 /* need the tag_len on the end for TinyDTLS to do its work - yuk */
1299 if (!coap_pdu_resize(plain_pdu, encrypt_len /* - tag_len */)) {
1300 if (!coap_request)
1301 coap_handle_event(session->context,
1303 session);
1304 goto error;
1305 }
1306
1307 /* Account for 1 byte 'code' used as token */
1308 plain_pdu->e_token_length = 1;
1309 plain_pdu->actual_token.length = 1;
1310 /* Account for the decrypted data */
1311 plain_pdu->used_size = encrypt_len - tag_len;
1312
1313 dump_cose(cose, "Pre decrypt");
1314 pltxt_size =
1315 cose_encrypt0_decrypt(cose, plain_pdu->token, encrypt_len - tag_len);
1316 if (pltxt_size <= 0) {
1317 coap_log_warn("OSCORE: Decryption Failure, result code: %d \n",
1318 (int)pltxt_size);
1319 if (coap_request) {
1320 build_and_send_error_pdu(session,
1321 pdu,
1322 COAP_RESPONSE_CODE(400),
1323 "Decryption failed",
1324 NULL,
1325 NULL,
1326 0);
1327 oscore_roll_back_seq(rcp_ctx);
1328 goto error_no_ack;
1329 } else {
1330 coap_handle_event(session->context,
1332 session);
1333 }
1334 goto error;
1335 }
1336
1337 assert((size_t)pltxt_size < pdu->alloc_size + pdu->max_hdr_size);
1338
1339 /* Appendix B.2 Trap */
1340 if (session->b_2_step == COAP_OSCORE_B_2_STEP_2) {
1341 /* Need to update Security Context with new (R2 || ID1) ID Context */
1342 coap_binary_t *kc =
1343 coap_new_binary(sizeof(session->oscore_r2) + cose->kid_context.length);
1344 coap_bin_const_t oscore_r2;
1345
1346 if (kc == NULL) {
1347 if (!coap_request)
1348 coap_handle_event(session->context,
1350 session);
1351 goto error;
1352 }
1353
1354 coap_prng(&session->oscore_r2, sizeof(session->oscore_r2));
1355 memcpy(kc->s, &session->oscore_r2, sizeof(session->oscore_r2));
1356 memcpy(&kc->s[sizeof(session->oscore_r2)],
1357 cose->kid_context.s,
1358 cose->kid_context.length);
1359
1360 coap_log_oscore("Appendix B.2 server step 2 (R2 || ID1)\n");
1361 oscore_update_ctx(osc_ctx, (coap_bin_const_t *)kc);
1362
1363 oscore_r2.length = sizeof(session->oscore_r2);
1364 oscore_r2.s = (const uint8_t *)&session->oscore_r2;
1365 coap_log_oscore("Appendix B.2 server step 2 plain response\n");
1366 build_and_send_error_pdu(session,
1367 pdu,
1368 COAP_RESPONSE_CODE(401),
1369 NULL,
1370 NULL,
1371 &oscore_r2,
1372 1);
1373 goto error_no_ack;
1374 }
1375#if COAP_CLIENT_SUPPORT
1376 if (session->b_2_step == COAP_OSCORE_B_2_STEP_3) {
1377 coap_log_oscore("Appendix B.2 client step 3 (R2 || R3)\n");
1378 coap_pdu_encode_header(plain_pdu, session->proto);
1379 plain_pdu->actual_token.s = plain_pdu->token;
1380 plain_pdu->code = plain_pdu->token[0];
1381 if (plain_pdu->code != COAP_RESPONSE_CODE(401)) {
1382 coap_log_warn("OSCORE Appendix B.2: Expected 4.01 response\n");
1383 }
1384 /* Skip the options */
1385 coap_option_iterator_init(plain_pdu, &opt_iter, COAP_OPT_ALL);
1386 while ((opt = coap_option_next(&opt_iter))) {
1387 }
1388 if (opt_iter.length > 0 && opt_iter.next_option &&
1389 opt_iter.next_option[0] == COAP_PAYLOAD_START) {
1390 plain_pdu->data = &opt_iter.next_option[1];
1391 }
1392 coap_log_oscore("Inner Response PDU (plaintext)\n");
1393 coap_show_pdu(COAP_LOG_OSCORE, plain_pdu);
1394 /*
1395 * Need to update Security Context with new (R2 || R3) ID Context
1396 * and retransmit the request
1397 */
1399
1400 if (kc == NULL) {
1401 if (!coap_request)
1402 coap_handle_event(session->context,
1404 session);
1405 goto error;
1406 }
1407 memcpy(kc->s, cose->kid_context.s, cose->kid_context.length);
1408 coap_prng(&kc->s[cose->kid_context.length], 8);
1409
1410 oscore_update_ctx(osc_ctx, (coap_bin_const_t *)kc);
1411
1413 session,
1414 &pdu->actual_token);
1415 if (session->con_active)
1416 session->con_active--;
1417 coap_send_ack(session, pdu);
1418 if (sent_pdu) {
1419 coap_log_oscore("Appendix B.2 retransmit pdu\n");
1420 if (coap_retransmit_oscore_pdu(session, sent_pdu, NULL) ==
1422 goto error_no_ack;
1423 }
1424 goto error_no_ack;
1425 }
1426#endif /* COAP_CLIENT_SUPPORT */
1427
1428#if COAP_SERVER_SUPPORT
1429 /* Appendix B.1.2 request Trap */
1430 if (coap_request && osc_ctx->rfc8613_b_1_2) {
1431 if (rcp_ctx->initial_state == 1) {
1432 opt = coap_check_option(plain_pdu, COAP_OPTION_ECHO, &opt_iter);
1433 if (opt) {
1434 /* Verify Client is genuine */
1435 if (coap_opt_length(opt) == 8 &&
1436 memcmp(coap_opt_value(opt), rcp_ctx->echo_value, 8) == 0) {
1437 if (!oscore_validate_sender_seq(rcp_ctx, cose)) {
1438 coap_log_warn("OSCORE: Replayed or old message\n");
1439 build_and_send_error_pdu(session,
1440 pdu,
1441 COAP_RESPONSE_CODE(401),
1442 "Replay detected",
1443 NULL,
1444 NULL,
1445 0);
1446 goto error_no_ack;
1447 }
1448 } else
1449 goto error;
1450 } else {
1451 /* RFC 8163 Appendix B.1.2 */
1452 if (session->b_2_step == COAP_OSCORE_B_2_STEP_4) {
1453 session->b_2_step = COAP_OSCORE_B_2_NONE;
1454 coap_log_oscore("Appendix B.2 server finished\n");
1455 }
1456 coap_prng(rcp_ctx->echo_value, sizeof(rcp_ctx->echo_value));
1457 coap_log_oscore("Appendix B.1.2 server plain response\n");
1458 build_and_send_error_pdu(session,
1459 pdu,
1460 COAP_RESPONSE_CODE(401),
1461 NULL,
1462 rcp_ctx->echo_value,
1463 NULL,
1464 1);
1465 goto error_no_ack;
1466 }
1467 }
1468 }
1469#endif /* COAP_SERVER_SUPPORT */
1470
1471 /*
1472 * 8.2 Step 7 / 8.4 Step 6.
1473 * Add decrypted Code, options and payload
1474 * [OSCORE option not copied across previously]
1475 */
1476
1477 /* PDU code is pseudo plain_pdu token */
1478 decrypt_pdu->code = plain_pdu->token[0];
1479
1480 /* Copy inner decrypted options across */
1481 coap_option_iterator_init(plain_pdu, &opt_iter, COAP_OPT_ALL);
1482 while ((opt = coap_option_next(&opt_iter))) {
1483 size_t len;
1484 size_t bias;
1485
1486 switch (opt_iter.number) {
1487 case COAP_OPTION_OSCORE:
1488 break;
1490 if (!coap_request) {
1491 bias = cose->partial_iv.length > 3 ? cose->partial_iv.length - 3 : 0;
1492 len = cose->partial_iv.length > 3 ? 3 : cose->partial_iv.length;
1493 /* Make Observe option reflect last 3 bytes of partial_iv */
1495 decrypt_pdu,
1496 opt_iter.number,
1497 len,
1498 cose->partial_iv.s ? &cose->partial_iv.s[bias] : NULL)) {
1499 coap_handle_event(session->context,
1501 session);
1502 goto error;
1503 }
1504 break;
1505 }
1506 association = oscore_find_association(session, &pdu_token);
1507 if (association) {
1508 association->is_observe = 1;
1509 association = NULL;
1510 }
1511 /* Fall Through */
1512 default:
1513 if (!coap_insert_option(decrypt_pdu,
1514 opt_iter.number,
1515 coap_opt_length(opt),
1516 coap_opt_value(opt))) {
1517 if (!coap_request)
1518 coap_handle_event(session->context,
1520 session);
1521 goto error;
1522 }
1523 break;
1524 }
1525 }
1526 /* Need to copy across any data */
1527 if (opt_iter.length > 0 && opt_iter.next_option &&
1528 opt_iter.next_option[0] == COAP_PAYLOAD_START) {
1529 plain_pdu->data = &opt_iter.next_option[1];
1530 if (!coap_add_data(decrypt_pdu,
1531 plain_pdu->used_size -
1532 (plain_pdu->data - plain_pdu->token),
1533 plain_pdu->data)) {
1534 if (!coap_request)
1535 coap_handle_event(session->context,
1537 session);
1538 goto error;
1539 }
1540 }
1541 coap_delete_pdu(plain_pdu);
1542 plain_pdu = NULL;
1543
1544 /* Make sure headers are correctly set up */
1545 if (!coap_pdu_encode_header(decrypt_pdu, session->proto)) {
1546 if (!coap_request)
1547 coap_handle_event(session->context,
1549 session);
1550 goto error;
1551 }
1552
1553 if (session->b_2_step != COAP_OSCORE_B_2_NONE) {
1554 session->b_2_step = COAP_OSCORE_B_2_NONE;
1555 coap_log_oscore("Appendix B.2 client finished\n");
1556 }
1557#if COAP_CLIENT_SUPPORT
1558 if (decrypt_pdu->code == COAP_RESPONSE_CODE(401) &&
1559 (opt = coap_check_option(decrypt_pdu, COAP_OPTION_ECHO, &opt_iter))) {
1560 /* Server is requesting Echo refresh check */
1562 session,
1563 &pdu->actual_token);
1564 if (session->con_active)
1565 session->con_active--;
1566 if (sent_pdu) {
1567 coap_send_ack(session, pdu);
1568 coap_log_debug("PDU requesting re-transmit\n");
1569 coap_show_pdu(COAP_LOG_DEBUG, decrypt_pdu);
1570 coap_log_oscore("RFC9175 retransmit pdu\n");
1571 /* Do not care if this fails */
1572 coap_retransmit_oscore_pdu(session, sent_pdu, opt);
1573 goto error_no_ack;
1574 }
1575 }
1576#endif /* COAP_CLIENT_SUPPORT */
1577 if (association && association->is_observe == 0)
1578 oscore_delete_association(session, association);
1579 return decrypt_pdu;
1580
1581error:
1582 coap_send_ack(session, pdu);
1583error_no_ack:
1584 if (association && association->is_observe == 0)
1585 oscore_delete_association(session, association);
1586 coap_delete_pdu(decrypt_pdu);
1587 coap_delete_pdu(plain_pdu);
1588 return NULL;
1589}
1590
1591typedef enum {
1592 COAP_ENC_ASCII = 0x01,
1593 COAP_ENC_HEX = 0x02,
1594 COAP_ENC_INTEGER = 0x08,
1595 COAP_ENC_TEXT = 0x10,
1596 COAP_ENC_BOOL = 0x20,
1597 COAP_ENC_LAST
1598} coap_oscore_coding_t;
1599
1600#undef TEXT_MAPPING
1601#define TEXT_MAPPING(t, v) \
1602 { { sizeof(#t)-1, (const uint8_t *)#t }, v }
1603
1604static struct coap_oscore_encoding_t {
1605 coap_str_const_t name;
1606 coap_oscore_coding_t encoding;
1607} oscore_encoding[] = {
1608 TEXT_MAPPING(ascii, COAP_ENC_ASCII),
1609 TEXT_MAPPING(hex, COAP_ENC_HEX),
1610 TEXT_MAPPING(integer, COAP_ENC_INTEGER),
1611 TEXT_MAPPING(text, COAP_ENC_TEXT),
1612 TEXT_MAPPING(bool, COAP_ENC_BOOL),
1613 {{0, NULL}, COAP_ENC_LAST}
1614};
1615
1616typedef struct {
1617 coap_oscore_coding_t encoding;
1618 const char *encoding_name;
1619 union {
1620 int value_int;
1621 coap_bin_const_t *value_bin;
1622 coap_str_const_t value_str;
1623 } u;
1624} oscore_value_t;
1625
1626static uint8_t
1627hex2char(char c) {
1628 assert(isxdigit(c));
1629 if ('a' <= c && c <= 'f')
1630 return c - 'a' + 10;
1631 else if ('A' <= c && c <= 'F')
1632 return c - 'A' + 10;
1633 else
1634 return c - '0';
1635}
1636
1637/* Parse the hex into binary */
1638static coap_bin_const_t *
1639parse_hex_bin(const char *begin, const char *end) {
1640 coap_binary_t *binary = NULL;
1641 size_t i;
1642
1643 if ((end - begin) % 2 != 0)
1644 goto bad_entry;
1645 binary = coap_new_binary((end - begin) / 2);
1646 if (binary == NULL)
1647 goto bad_entry;
1648 for (i = 0; (i < (size_t)(end - begin)) && isxdigit((u_char)begin[i]) &&
1649 isxdigit((u_char)begin[i + 1]);
1650 i += 2) {
1651 binary->s[i / 2] = (hex2char(begin[i]) << 4) + hex2char(begin[i + 1]);
1652 }
1653 if (i != (size_t)(end - begin))
1654 goto bad_entry;
1655 return (coap_bin_const_t *)binary;
1656
1657bad_entry:
1658 coap_delete_binary(binary);
1659 return NULL;
1660}
1661
1662/*
1663 * Break up each OSCORE Configuration line entry into the 3 parts which
1664 * are comma separated
1665 *
1666 * keyword,encoding,value
1667 */
1668static int
1669get_split_entry(const char **start,
1670 size_t size,
1671 coap_str_const_t *keyword,
1672 oscore_value_t *value) {
1673 const char *begin = *start;
1674 const char *end;
1675 const char *split;
1676 size_t i;
1677
1678retry:
1679 end = memchr(begin, '\n', size);
1680 if (end == NULL)
1681 return 0;
1682
1683 /* Track beginning of next line */
1684 *start = end + 1;
1685 if (end > begin && end[-1] == '\r')
1686 end--;
1687
1688 if (begin[0] == '#' || (end - begin) == 0) {
1689 /* Skip comment / blank line */
1690 size -= end - begin + 1;
1691 begin = *start;
1692 goto retry;
1693 }
1694
1695 /* Get in the keyword */
1696 split = memchr(begin, ',', end - begin);
1697 if (split == NULL)
1698 goto bad_entry;
1699
1700 keyword->s = (const uint8_t *)begin;
1701 keyword->length = split - begin;
1702
1703 begin = split + 1;
1704 if ((end - begin) == 0)
1705 goto bad_entry;
1706 /* Get in the encoding */
1707 split = memchr(begin, ',', end - begin);
1708 if (split == NULL)
1709 goto bad_entry;
1710
1711 for (i = 0; oscore_encoding[i].name.s; i++) {
1712 coap_str_const_t temp = { split - begin, (const uint8_t *)begin };
1713
1714 if (coap_string_equal(&temp, &oscore_encoding[i].name)) {
1715 value->encoding = oscore_encoding[i].encoding;
1716 value->encoding_name = (const char *)oscore_encoding[i].name.s;
1717 break;
1718 }
1719 }
1720 if (oscore_encoding[i].name.s == NULL)
1721 goto bad_entry;
1722
1723 begin = split + 1;
1724 if ((end - begin) == 0)
1725 goto bad_entry;
1726 /* Get in the keyword's value */
1727 if (begin[0] == '"') {
1728 split = memchr(&begin[1], '"', end - split - 1);
1729 if (split == NULL)
1730 goto bad_entry;
1731 end = split;
1732 begin++;
1733 }
1734 switch (value->encoding) {
1735 case COAP_ENC_ASCII:
1736 value->u.value_bin =
1737 coap_new_bin_const((const uint8_t *)begin, end - begin);
1738 break;
1739 case COAP_ENC_HEX:
1740 /* Parse the hex into binary */
1741 value->u.value_bin = parse_hex_bin(begin, end);
1742 if (value->u.value_bin == NULL)
1743 goto bad_entry;
1744 break;
1745 case COAP_ENC_INTEGER:
1746 value->u.value_int = atoi(begin);
1747 break;
1748 case COAP_ENC_TEXT:
1749 value->u.value_str.s = (const uint8_t *)begin;
1750 value->u.value_str.length = end - begin;
1751 break;
1752 case COAP_ENC_BOOL:
1753 if (memcmp("true", begin, end - begin) == 0)
1754 value->u.value_int = 1;
1755 else if (memcmp("false", begin, end - begin) == 0)
1756 value->u.value_int = 0;
1757 else
1758 goto bad_entry;
1759 break;
1760 case COAP_ENC_LAST:
1761 default:
1762 goto bad_entry;
1763 }
1764 return 1;
1765
1766bad_entry:
1767 coap_log_warn("oscore_conf: Unrecognized configuration entry '%.*s'\n",
1768 (int)(end - begin),
1769 begin);
1770 return 0;
1771}
1772
1773#undef CONFIG_ENTRY
1774#define CONFIG_ENTRY(n, e, t) \
1775 { { sizeof(#n)-1, (const uint8_t *)#n }, e, \
1776 offsetof(coap_oscore_conf_t, n), t }
1777
1778typedef struct oscore_text_mapping_t {
1779 coap_str_const_t text;
1780 int value;
1781} oscore_text_mapping_t;
1782
1783/* Naming as per https://www.iana.org/assignments/cose/cose.xhtml#algorithms */
1784static oscore_text_mapping_t text_aead_alg[] = {
1785 TEXT_MAPPING(AES-CCM-16-64-128, COSE_ALGORITHM_AES_CCM_16_64_128),
1786 TEXT_MAPPING(AES-CCM-16-64-256, COSE_ALGORITHM_AES_CCM_16_64_256),
1787 {{0, NULL}, 0}
1788};
1789
1790static oscore_text_mapping_t text_hkdf_alg[] = {
1791 TEXT_MAPPING(direct+HKDF-SHA-256, COSE_HKDF_ALG_HKDF_SHA_256),
1792 {{0, NULL}, 0}
1793};
1794
1795static struct oscore_config_t {
1796 coap_str_const_t str_keyword;
1797 coap_oscore_coding_t encoding;
1798 size_t offset;
1799 oscore_text_mapping_t *text_mapping;
1800} oscore_config[] = {
1801 CONFIG_ENTRY(master_secret, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
1802 CONFIG_ENTRY(master_salt, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
1803 CONFIG_ENTRY(sender_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
1804 CONFIG_ENTRY(id_context, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
1805 CONFIG_ENTRY(recipient_id, COAP_ENC_HEX | COAP_ENC_ASCII, NULL),
1806 CONFIG_ENTRY(replay_window, COAP_ENC_INTEGER, NULL),
1807 CONFIG_ENTRY(ssn_freq, COAP_ENC_INTEGER, NULL),
1808 CONFIG_ENTRY(aead_alg, COAP_ENC_INTEGER | COAP_ENC_TEXT, text_aead_alg),
1809 CONFIG_ENTRY(hkdf_alg, COAP_ENC_INTEGER | COAP_ENC_TEXT, text_hkdf_alg),
1810 CONFIG_ENTRY(rfc8613_b_1_2, COAP_ENC_BOOL, NULL),
1811 CONFIG_ENTRY(rfc8613_b_2, COAP_ENC_BOOL, NULL),
1812 CONFIG_ENTRY(break_sender_key, COAP_ENC_BOOL, NULL),
1813 CONFIG_ENTRY(break_recipient_key, COAP_ENC_BOOL, NULL),
1814};
1815
1816int
1818 uint32_t i;
1819
1820 if (oscore_conf == NULL)
1821 return 0;
1822
1824 coap_delete_bin_const(oscore_conf->master_salt);
1825 coap_delete_bin_const(oscore_conf->id_context);
1826 coap_delete_bin_const(oscore_conf->sender_id);
1827 for (i = 0; i < oscore_conf->recipient_id_count; i++) {
1828 coap_delete_bin_const(oscore_conf->recipient_id[i]);
1829 }
1831 coap_free_type(COAP_STRING, oscore_conf);
1832 return 1;
1833}
1834
1835static coap_oscore_conf_t *
1836coap_parse_oscore_conf_mem(coap_str_const_t conf_mem) {
1837 const char *start = (const char *)conf_mem.s;
1838 const char *end = start + conf_mem.length;
1839 coap_str_const_t keyword;
1840 oscore_value_t value;
1841 coap_oscore_conf_t *oscore_conf;
1842
1843 oscore_conf = coap_malloc_type(COAP_STRING, sizeof(coap_oscore_conf_t));
1844 if (oscore_conf == NULL)
1845 return NULL;
1846 memset(oscore_conf, 0, sizeof(coap_oscore_conf_t));
1847
1848 memset(&value, 0, sizeof(value));
1849 /* Preset with defaults */
1851 oscore_conf->ssn_freq = 1;
1853 oscore_conf->hkdf_alg = COSE_HKDF_ALG_HKDF_SHA_256;
1854 oscore_conf->rfc8613_b_1_2 = 1;
1855 oscore_conf->rfc8613_b_2 = 0;
1856 oscore_conf->break_sender_key = 0;
1857 oscore_conf->break_recipient_key = 0;
1858
1859 while (end > start &&
1860 get_split_entry(&start, end - start, &keyword, &value)) {
1861 size_t i;
1862 size_t j;
1863
1864 for (i = 0; i < sizeof(oscore_config) / sizeof(oscore_config[0]); i++) {
1865 if (coap_string_equal(&oscore_config[i].str_keyword, &keyword) != 0 &&
1866 value.encoding & oscore_config[i].encoding) {
1867 if (coap_string_equal(coap_make_str_const("recipient_id"), &keyword)) {
1868 if (value.u.value_bin->length > 7) {
1869 coap_log_warn("oscore_conf: Maximum size of recipient_id is 7 bytes\n");
1870 goto error_free_value_bin;
1871 }
1872 /* Special case as there are potentially multiple entries */
1873 oscore_conf->recipient_id =
1875 oscore_conf->recipient_id,
1876 sizeof(oscore_conf->recipient_id[0]) *
1877 (oscore_conf->recipient_id_count + 1));
1878 if (oscore_conf->recipient_id == NULL) {
1879 goto error_free_value_bin;
1880 }
1881 oscore_conf->recipient_id[oscore_conf->recipient_id_count++] =
1882 value.u.value_bin;
1883 } else {
1884 coap_bin_const_t *unused_check;
1885
1886 switch (value.encoding) {
1887 case COAP_ENC_HEX:
1888 case COAP_ENC_ASCII:
1889 memcpy(&unused_check,
1890 &(((char *)oscore_conf)[oscore_config[i].offset]),
1891 sizeof(unused_check));
1892 if (unused_check != NULL) {
1893 coap_log_warn("oscore_conf: Keyword '%.*s' duplicated\n",
1894 (int)keyword.length,
1895 (const char *)keyword.s);
1896 goto error;
1897 }
1898 memcpy(&(((char *)oscore_conf)[oscore_config[i].offset]),
1899 &value.u.value_bin,
1900 sizeof(value.u.value_bin));
1901 break;
1902 case COAP_ENC_INTEGER:
1903 case COAP_ENC_BOOL:
1904 memcpy(&(((char *)oscore_conf)[oscore_config[i].offset]),
1905 &value.u.value_int,
1906 sizeof(value.u.value_int));
1907 break;
1908 case COAP_ENC_TEXT:
1909 for (j = 0; oscore_config[i].text_mapping[j].text.s != NULL; j++) {
1910 if (coap_string_equal(&value.u.value_str,
1911 &oscore_config[i].text_mapping[j].text)) {
1912 memcpy(&(((char *)oscore_conf)[oscore_config[i].offset]),
1913 &oscore_config[i].text_mapping[j].value,
1914 sizeof(oscore_config[i].text_mapping[j].value));
1915 break;
1916 }
1917 }
1918 if (oscore_config[i].text_mapping[j].text.s == NULL) {
1919 coap_log_warn("oscore_conf: Keyword '%.*s': value '%.*s' unknown\n",
1920 (int)keyword.length,
1921 (const char *)keyword.s,
1922 (int)value.u.value_str.length,
1923 (const char *)value.u.value_str.s);
1924 goto error;
1925 }
1926 break;
1927 case COAP_ENC_LAST:
1928 default:
1929 assert(0);
1930 break;
1931 }
1932 }
1933 break;
1934 }
1935 }
1936 if (i == sizeof(oscore_config) / sizeof(oscore_config[0])) {
1937 coap_log_warn("oscore_conf: Keyword '%.*s', type '%s' unknown\n",
1938 (int)keyword.length,
1939 (const char *)keyword.s,
1940 value.encoding_name);
1941 if (value.encoding == COAP_ENC_HEX || value.encoding == COAP_ENC_ASCII)
1942 coap_delete_bin_const(value.u.value_bin);
1943 goto error;
1944 }
1945 }
1946 if (!oscore_conf->master_secret) {
1947 coap_log_warn("oscore_conf: master_secret not defined\n");
1948 goto error;
1949 }
1950 if (!oscore_conf->sender_id) {
1951 coap_log_warn("oscore_conf: sender_id not defined\n");
1952 goto error;
1953 }
1954 if (oscore_conf->sender_id->length > 7) {
1955 coap_log_warn("oscore_conf: Maximum size of sender_id is 7 bytes\n");
1956 goto error;
1957 }
1958 if (oscore_conf->recipient_id && oscore_conf->recipient_id[0]->length > 7) {
1959 coap_log_warn("oscore_conf: Maximum size of recipient_id is 7 bytes\n");
1960 goto error;
1961 }
1962 return oscore_conf;
1963
1964error_free_value_bin:
1965 coap_delete_bin_const(value.u.value_bin);
1966error:
1967 coap_delete_oscore_conf(oscore_conf);
1968 return NULL;
1969}
1970
1971static oscore_ctx_t *
1972coap_oscore_init(coap_context_t *c_context, coap_oscore_conf_t *oscore_conf) {
1973 oscore_ctx_t *osc_ctx = NULL;
1974
1975 if (!coap_crypto_check_cipher_alg(oscore_conf->aead_alg)) {
1976 coap_log_warn("COSE: Cipher Algorithm %d not supported\n",
1977 oscore_conf->aead_alg);
1978 goto error;
1979 }
1980 if (!coap_crypto_check_hkdf_alg(oscore_conf->hkdf_alg)) {
1981 coap_log_warn("COSE: HKDF Algorithm %d not supported\n",
1982 oscore_conf->hkdf_alg);
1983 goto error;
1984 }
1985
1986 osc_ctx = oscore_derive_ctx(c_context, oscore_conf);
1987 if (!osc_ctx) {
1988 coap_log_crit("OSCORE: Could not create Security Context!\n");
1989 goto error;
1990 }
1991
1992 /* Free off the recipient_id array */
1994 oscore_conf->recipient_id = NULL;
1995
1996 /* As all is stored in osc_ctx, oscore_conf is no longer needed */
1997 coap_free_type(COAP_STRING, oscore_conf);
1998
1999 /* return default first context */
2000 return osc_ctx;
2001
2002error:
2003 /* Remove from linked chain */
2004 oscore_remove_context(c_context, osc_ctx);
2005
2006 coap_delete_oscore_conf(oscore_conf);
2007 return NULL;
2008}
2009
2010void
2012 oscore_free_contexts(c_context);
2013}
2014
2015void
2018}
2019
2022 coap_oscore_save_seq_num_t save_seq_num_func,
2023 void *save_seq_num_func_param,
2024 uint64_t start_seq_num) {
2025 coap_oscore_conf_t *oscore_conf = coap_parse_oscore_conf_mem(conf_mem);
2026
2027 if (oscore_conf == NULL)
2028 return NULL;
2029
2030 oscore_conf->save_seq_num_func = save_seq_num_func;
2031 oscore_conf->save_seq_num_func_param = save_seq_num_func_param;
2032 oscore_conf->start_seq_num = start_seq_num;
2033 coap_log_oscore("Start Seq no %" PRIu64 "\n", start_seq_num);
2034 return oscore_conf;
2035}
2036
2037/*
2038 * Compute the size of the potential OSCORE overhead
2039 */
2040size_t
2042 size_t overhead = 0;
2043 oscore_recipient_ctx_t *rcp_ctx = session->recipient_ctx;
2044 oscore_ctx_t *osc_ctx = rcp_ctx ? rcp_ctx->osc_ctx : NULL;
2045 coap_opt_iterator_t opt_iter;
2046 coap_opt_t *option;
2047
2048 if (osc_ctx == NULL)
2049 return 0;
2050
2051 /* Protected code held in inner PDU as token */
2052 overhead += 1;
2053
2054 /* Observe option (creates inner and outer */
2055 option = coap_check_option(pdu, COAP_OPTION_OBSERVE, &opt_iter);
2056 if (option) {
2057 /* Assume delta is small */
2058 overhead += 2 + coap_opt_length(option);
2059 }
2060
2061 /* Proxy URI option Split - covered by coap_rebuild_pdu_for_proxy () */
2062
2063 /* OSCORE option */
2064 /* Option header */
2065 overhead += 1 +
2066 /* Partial IV (64 bits max)*/
2067 8 +
2068 /* kid context */
2069 (osc_ctx->id_context ? osc_ctx->id_context->length : 0) +
2070 /* kid */
2071 osc_ctx->sender_context->sender_id->length;
2072
2073 /* AAD overhead */
2074 overhead += AES_CCM_TAG;
2075
2076 /* End of options marker */
2077 overhead += 1;
2078
2079 return overhead;
2080}
2081
2082int
2084 coap_bin_const_t *recipient_id) {
2085 if (context->p_osc_ctx == NULL)
2086 return 0;
2087 if (oscore_add_recipient(context->p_osc_ctx, recipient_id, 0) == NULL)
2088 return 0;
2089 return 1;
2090}
2091
2092int
2094 coap_bin_const_t *recipient_id) {
2095 if (context->p_osc_ctx == NULL)
2096 return 0;
2097 return oscore_delete_recipient(context->p_osc_ctx, recipient_id);
2098}
2099
2102#else /* !COAP_OSCORE_SUPPORT */
2103int
2105 return 0;
2106}
2107
2110 const coap_address_t *local_if,
2111 const coap_address_t *server,
2112 coap_proto_t proto,
2113 coap_oscore_conf_t *oscore_conf) {
2114 (void)ctx;
2115 (void)local_if;
2116 (void)server;
2117 (void)proto;
2118 (void)oscore_conf;
2119 return NULL;
2120}
2121
2124 const coap_address_t *local_if,
2125 const coap_address_t *server,
2126 coap_proto_t proto,
2127 coap_dtls_cpsk_t *psk_data,
2128 coap_oscore_conf_t *oscore_conf) {
2129 (void)ctx;
2130 (void)local_if;
2131 (void)server;
2132 (void)proto;
2133 (void)psk_data;
2134 (void)oscore_conf;
2135 return NULL;
2136}
2137
2140 const coap_address_t *local_if,
2141 const coap_address_t *server,
2142 coap_proto_t proto,
2143 coap_dtls_pki_t *pki_data,
2144 coap_oscore_conf_t *oscore_conf) {
2145 (void)ctx;
2146 (void)local_if;
2147 (void)server;
2148 (void)proto;
2149 (void)pki_data;
2150 (void)oscore_conf;
2151 return NULL;
2152}
2153
2154int
2156 coap_oscore_conf_t *oscore_conf) {
2157 (void)context;
2158 (void)oscore_conf;
2159 return 0;
2160}
2161
2164 coap_oscore_save_seq_num_t save_seq_num_func,
2165 void *save_seq_num_func_param,
2166 uint64_t start_seq_num) {
2167 (void)conf_mem;
2168 (void)save_seq_num_func;
2169 (void)save_seq_num_func_param;
2170 (void)start_seq_num;
2171 return NULL;
2172}
2173
2174int
2176 (void)oscore_conf;
2177 return 0;
2178}
2179
2180int
2182 coap_bin_const_t *recipient_id) {
2183 (void)context;
2184 (void)recipient_id;
2185 return 0;
2186}
2187
2188int
2190 coap_bin_const_t *recipient_id) {
2191 (void)context;
2192 (void)recipient_id;
2193 return 0;
2194}
2195
2196#endif /* !COAP_OSCORE_SUPPORT */
Pulls together all the internal only header files.
#define PRIu64
Definition: coap_internal.h:51
@ COAP_OSCORE_BUF
Definition: coap_mem.h:65
@ COAP_STRING
Definition: coap_mem.h:38
void * coap_realloc_type(coap_memory_tag_t type, void *p, size_t size)
Reallocates a chunk p of bytes created by coap_malloc_type() or coap_realloc_type() and returns a poi...
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().
size_t coap_opt_size(const coap_opt_t *opt)
Returns the size of the given option, taking into account a possible option jump.
Definition: coap_option.c:284
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:26
static int coap_uri_scheme_is_secure(const coap_uri_t *uri)
Definition: coap_uri.h:79
@ COAP_URI_SCHEME_LAST
Definition: coap_uri.h:37
coap_mid_t coap_retransmit_oscore_pdu(coap_session_t *session, coap_pdu_t *pdu, coap_opt_t *echo)
int coap_prng(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition: coap_prng.c:140
coap_mid_t coap_send_internal(coap_session_t *session, coap_pdu_t *pdu)
Sends a CoAP message to given peer.
Definition: coap_net.c:1381
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:2323
coap_mid_t coap_send_ack(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:770
uint16_t coap_new_message_id(coap_session_t *session)
Returns a new message id and updates session->tx_mid accordingly.
int coap_handle_event(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:3917
#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:67
unsigned int coap_encode_var_safe8(uint8_t *buf, size_t length, uint64_t val)
Encodes multiple-length byte sequences.
Definition: coap_encode.c:77
@ COAP_EVENT_OSCORE_DECODE_ERROR
Triggered when there is an OSCORE decode of OSCORE option failure.
Definition: coap_event.h:118
@ COAP_EVENT_OSCORE_INTERNAL_ERROR
Triggered when there is an OSCORE internal error i.e malloc failed.
Definition: coap_event.h:116
@ COAP_EVENT_OSCORE_NOT_ENABLED
Triggered when trying to use OSCORE to decrypt, but it is not enabled.
Definition: coap_event.h:110
@ COAP_EVENT_OSCORE_NO_SECURITY
Triggered when there is no OSCORE security definition found.
Definition: coap_event.h:114
@ COAP_EVENT_OSCORE_NO_PROTECTED_PAYLOAD
Triggered when there is no OSCORE encrypted payload provided.
Definition: coap_event.h:112
@ COAP_EVENT_OSCORE_DECRYPTION_FAILURE
Triggered when there is an OSCORE decryption failure.
Definition: coap_event.h:108
#define coap_log_debug(...)
Definition: coap_debug.h:120
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition: coap_debug.c:91
void coap_show_pdu(coap_log_t level, const coap_pdu_t *pdu)
Display the contents of the specified pdu.
Definition: coap_debug.c:703
#define coap_log_oscore(...)
Definition: coap_debug.h:126
#define coap_log_warn(...)
Definition: coap_debug.h:102
#define coap_log_crit(...)
Definition: coap_debug.h:90
@ COAP_LOG_OSCORE
Definition: coap_debug.h:59
@ COAP_LOG_DEBUG
Definition: coap_debug.h:58
coap_opt_t * coap_option_next(coap_opt_iterator_t *oi)
Updates the iterator oi to point to the next option.
Definition: coap_option.c:153
uint32_t coap_opt_length(const coap_opt_t *opt)
Returns the length of the given option.
Definition: coap_option.c:212
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.
Definition: coap_option.c:117
#define COAP_OPT_ALL
Pre-defined filter that includes all options.
Definition: coap_option.h:108
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.
Definition: coap_option.c:199
const uint8_t * coap_opt_value(const coap_opt_t *opt)
Returns a pointer to the value of the given option.
Definition: coap_option.c:249
size_t oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_len)
Definition: oscore_cbor.c:240
void cose_encrypt0_set_plaintext(cose_encrypt0_t *ptr, uint8_t *buffer, size_t size)
Definition: oscore_cose.c:315
int cose_encrypt0_set_key(cose_encrypt0_t *ptr, coap_bin_const_t *key)
Definition: oscore_cose.c:401
void cose_encrypt0_set_kid_context(cose_encrypt0_t *ptr, coap_bin_const_t *kid_context)
Definition: oscore_cose.c:368
const char * cose_get_alg_name(cose_alg_t id, char *buffer, size_t buflen)
Definition: oscore_cose.c:120
void cose_encrypt0_set_ciphertext(cose_encrypt0_t *ptr, uint8_t *buffer, size_t size)
Definition: oscore_cose.c:307
int cose_encrypt0_decrypt(cose_encrypt0_t *ptr, uint8_t *plaintext_buffer, size_t plaintext_len)
Definition: oscore_cose.c:460
size_t cose_tag_len(cose_alg_t cose_alg)
Definition: oscore_cose.c:196
void cose_encrypt0_set_aad(cose_encrypt0_t *ptr, coap_bin_const_t *aad)
Definition: oscore_cose.c:390
int cose_encrypt0_encrypt(cose_encrypt0_t *ptr, uint8_t *ciphertext_buffer, size_t ciphertext_len)
Definition: oscore_cose.c:421
void cose_encrypt0_set_partial_iv(cose_encrypt0_t *ptr, coap_bin_const_t *partial_iv)
Definition: oscore_cose.c:325
void cose_encrypt0_set_external_aad(cose_encrypt0_t *ptr, coap_bin_const_t *external_aad)
Definition: oscore_cose.c:379
void cose_encrypt0_init(cose_encrypt0_t *ptr)
Definition: oscore_cose.c:297
void cose_encrypt0_set_alg(cose_encrypt0_t *ptr, uint8_t alg)
Definition: oscore_cose.c:302
void cose_encrypt0_set_key_id(cose_encrypt0_t *ptr, coap_bin_const_t *key_id)
Definition: oscore_cose.c:346
void cose_encrypt0_set_nonce(cose_encrypt0_t *ptr, coap_bin_const_t *nonce)
Definition: oscore_cose.c:411
@ COSE_HKDF_ALG_HKDF_SHA_256
Definition: oscore_cose.h:167
@ COSE_ALGORITHM_AES_CCM_16_64_128
Definition: oscore_cose.h:145
@ COSE_ALGORITHM_AES_CCM_16_64_256
Definition: oscore_cose.h:146
size_t oscore_prepare_aad(const uint8_t *external_aad_buffer, size_t external_aad_len, uint8_t *aad_buffer, size_t aad_size)
Definition: oscore.c:312
size_t oscore_encode_option_value(uint8_t *option_buffer, size_t option_buf_len, cose_encrypt0_t *cose, uint8_t group_flag, uint8_t appendix_b_2)
Definition: oscore.c:170
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.
int oscore_delete_association(coap_session_t *session, oscore_association_t *association)
uint8_t oscore_validate_sender_seq(oscore_recipient_ctx_t *ctx, cose_encrypt0_t *cose)
Definition: oscore.c:366
oscore_recipient_ctx_t * oscore_add_recipient(oscore_ctx_t *osc_ctx, coap_bin_const_t *rid, uint32_t break_key)
oscore_add_recipient - add in recipient information
#define OSCORE_SEQ_MAX
#define AES_CCM_TAG
Definition: oscore_crypto.h:61
int oscore_decode_option_value(const uint8_t *opt_value, size_t option_len, cose_encrypt0_t *cose)
Definition: oscore.c:246
int oscore_delete_recipient(oscore_ctx_t *osc_ctx, coap_bin_const_t *rid)
uint8_t oscore_increment_sender_seq(oscore_ctx_t *ctx)
Definition: oscore.c:430
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
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
void oscore_roll_back_seq(oscore_recipient_ctx_t *ctx)
Definition: oscore.c:447
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)
Definition: oscore.c:119
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.
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)
Definition: oscore.c:343
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)
oscore_ctx_t * oscore_find_context(const coap_context_t *c_context, 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)
size_t coap_oscore_overhead(coap_session_t *session, coap_pdu_t *pdu)
Determine the additional data size requirements for adding in OSCORE.
@ OSCORE_MODE_SINGLE
Vanilla RFC8613 support.
@ 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.
Definition: coap_oscore.c:2163
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 ...
Definition: coap_oscore.c:2189
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 ...
Definition: coap_oscore.c:2123
int coap_delete_oscore_conf(coap_oscore_conf_t *oscore_conf)
Release all the information associated with the OSCORE configuration.
Definition: coap_oscore.c:2175
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
Definition: coap_oscore.c:2104
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.
Definition: coap_oscore.c:2109
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).
Definition: coap_oscore.c:2181
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 ...
Definition: coap_oscore.c:2139
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.
Definition: coap_oscore.c:2155
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.
Definition: coap_oscore.h:137
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:563
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:426
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:1405
#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:245
#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:701
#define COAP_OPTION_HOP_LIMIT
Definition: coap_pdu.h:129
#define COAP_OPTION_NORESPONSE
Definition: coap_pdu.h:141
#define COAP_OPTION_URI_HOST
Definition: coap_pdu.h:116
#define COAP_OPTION_IF_MATCH
Definition: coap_pdu.h:115
#define COAP_OPTION_BLOCK2
Definition: coap_pdu.h:133
#define COAP_OPTION_CONTENT_FORMAT
Definition: coap_pdu.h:124
#define COAP_OPTION_SIZE2
Definition: coap_pdu.h:135
#define COAP_OPTION_BLOCK1
Definition: coap_pdu.h:134
#define COAP_OPTION_PROXY_SCHEME
Definition: coap_pdu.h:138
#define COAP_DEFAULT_PORT
Definition: coap_pdu.h:37
#define COAP_OPTION_URI_QUERY
Definition: coap_pdu.h:128
void coap_delete_pdu(coap_pdu_t *pdu)
Dispose of an CoAP PDU and frees associated storage.
Definition: coap_pdu.c:163
#define COAP_OPTION_IF_NONE_MATCH
Definition: coap_pdu.h:118
#define COAP_OPTION_LOCATION_PATH
Definition: coap_pdu.h:121
#define COAP_OPTION_URI_PATH
Definition: coap_pdu.h:123
#define COAP_RESPONSE_CODE(N)
Definition: coap_pdu.h:152
coap_proto_t
CoAP protocol types.
Definition: coap_pdu.h:304
coap_pdu_code_t
Set of codes available for a PDU.
Definition: coap_pdu.h:318
#define COAP_OPTION_OSCORE
Definition: coap_pdu.h:122
#define COAP_OPTION_SIZE1
Definition: coap_pdu.h:139
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:304
#define COAP_OPTION_LOCATION_QUERY
Definition: coap_pdu.h:132
#define COAPS_DEFAULT_PORT
Definition: coap_pdu.h:38
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:797
#define COAP_OPTION_RTAG
Definition: coap_pdu.h:142
coap_pdu_t * coap_pdu_duplicate(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:179
#define COAP_OPTION_URI_PORT
Definition: coap_pdu.h:120
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:97
#define COAP_OPTION_ACCEPT
Definition: coap_pdu.h:130
#define COAP_INVALID_MID
Indicates an invalid message id.
Definition: coap_pdu.h:258
#define COAP_OPTION_MAXAGE
Definition: coap_pdu.h:127
#define COAP_OPTION_ETAG
Definition: coap_pdu.h:117
#define COAP_OPTION_PROXY_URI
Definition: coap_pdu.h:137
#define COAP_OPTION_OBSERVE
Definition: coap_pdu.h:119
#define COAP_OPTION_ECHO
Definition: coap_pdu.h:140
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:766
coap_bin_const_t coap_pdu_get_token(const coap_pdu_t *pdu)
Gets the token associated with pdu.
Definition: coap_pdu.c:1516
@ COAP_REQUEST_CODE_POST
Definition: coap_pdu.h:322
@ COAP_REQUEST_CODE_FETCH
Definition: coap_pdu.h:325
@ COAP_MESSAGE_NON
Definition: coap_pdu.h:66
@ COAP_MESSAGE_ACK
Definition: coap_pdu.h:67
@ COAP_MESSAGE_CON
Definition: coap_pdu.h:65
@ 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
coap_session_t * coap_new_client_session_pki(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)
Creates a new client session to the designated server with PKI credentials.
#define COAP_PROTO_NOT_RELIABLE(p)
Definition: coap_session.h:36
void coap_session_release(coap_session_t *session)
Decrement reference counter on a session.
Definition: coap_session.c:354
coap_session_t * coap_new_client_session(coap_context_t *ctx, const coap_address_t *local_if, const coap_address_t *server, coap_proto_t proto)
Creates a new client session to the designated server.
coap_session_t * coap_new_client_session_psk2(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)
Creates a new client session to the designated server with PSK credentials.
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:120
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:77
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:66
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:110
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition: coap_str.c:105
#define coap_binary_equal(binary1, binary2)
Compares the two binary data for equality.
Definition: coap_str.h:203
#define coap_string_equal(string1, string2)
Compares the two strings for equality.
Definition: coap_str.h:189
int coap_split_path(const uint8_t *s, size_t length, unsigned char *buf, size_t *buflen)
Splits the given URI path into segments.
Definition: coap_uri.c:600
int coap_split_query(const uint8_t *s, size_t length, unsigned char *buf, size_t *buflen)
Splits the given URI query into segments.
Definition: coap_uri.c:612
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:274
coap_uri_info_t coap_uri_scheme[COAP_URI_SCHEME_LAST]
Definition: coap_uri.c:51
Multi-purpose address abstraction.
Definition: coap_address.h:109
CoAP binary data definition with const data.
Definition: coap_str.h:64
size_t length
length of binary data
Definition: coap_str.h:65
const uint8_t * s
read-only binary data
Definition: coap_str.h:66
CoAP binary data definition.
Definition: coap_str.h:56
size_t length
length of binary data
Definition: coap_str.h:57
uint8_t * s
binary data
Definition: coap_str.h:58
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:378
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:284
Iterator to run through PDU options.
Definition: coap_option.h:168
coap_opt_t * next_option
pointer to the unparsed next option
Definition: coap_option.h:173
size_t length
remaining length of PDU
Definition: coap_option.h:169
coap_option_num_t number
decoded option number
Definition: coap_option.h:170
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
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.
coap_bin_const_t * sender_id
Sender ID (i.e.
coap_bin_const_t ** recipient_id
Recipient ID (i.e.
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.
uint32_t recipient_id_count
Number of recipient_id entries.
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...
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:46
const uint8_t * s
read-only string data
Definition: coap_str.h:48
size_t length
length of string
Definition: coap_str.h:47
const char * name
scheme name
Representation of parsed URI.
Definition: coap_uri.h:65
enum coap_uri_scheme_t scheme
The parsed scheme specifier.
Definition: coap_uri.h:75
coap_str_const_t path
The complete path if present or {0, NULL}.
Definition: coap_uri.h:68
uint16_t port
The port in host byte order.
Definition: coap_uri.h:67
coap_str_const_t query
The complete query if present or {0, NULL}.
Definition: coap_uri.h:71
coap_str_const_t host
The host part of the URI.
Definition: coap_uri.h:66
coap_bin_const_t aad
Definition: oscore_cose.h:208
coap_bin_const_t key
Definition: oscore_cose.h:199
coap_bin_const_t partial_iv
Definition: oscore_cose.h:202
coap_bin_const_t kid_context
Definition: oscore_cose.h:204
coap_bin_const_t nonce
Definition: oscore_cose.h:206
coap_bin_const_t external_aad
Definition: oscore_cose.h:207
coap_bin_const_t key_id
Definition: oscore_cose.h:203
coap_bin_const_t oscore_option
Definition: oscore_cose.h:205
cose_alg_t alg
Definition: oscore_cose.h:198
coap_bin_const_t * partial_iv
coap_bin_const_t * aad
coap_bin_const_t * nonce
oscore_recipient_ctx_t * recipient_ctx
oscore_mode_t mode
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
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
oscore_ctx_t * osc_ctx
coap_bin_const_t * sender_id
coap_bin_const_t * sender_key
uint64_t next_seq
Used for ssn_freq updating.