libcoap 4.3.5-develop-24d146d
Loading...
Searching...
No Matches
oscore_context.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 * Copyright (c) 2018, SICS, RISE AB
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Institute nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
47
48#if COAP_OSCORE_SUPPORT
49
50#include <stdio.h>
51
52/* Move ptr from b to a, and then clear b */
53#define OSC_MOVE_PTR(a,b) do { (a) = (b); (b) = NULL; } while(0)
54
55static size_t
56compose_info(uint8_t *buffer,
57 size_t buf_size,
58 cose_alg_t alg,
60 coap_bin_const_t *id_context,
61 coap_str_const_t *type,
62 size_t out_len) {
63 size_t ret = 0;
64 size_t rem_size = buf_size;
65
66 ret += oscore_cbor_put_array(&buffer, &rem_size, 5);
67 ret += oscore_cbor_put_bytes(&buffer,
68 &rem_size,
69 id ? id->s : NULL,
70 id ? id->length : 0);
71 if (id_context != NULL && id_context->length > 0) {
72 ret += oscore_cbor_put_bytes(&buffer,
73 &rem_size,
74 id_context->s,
75 id_context->length);
76 } else {
77 ret += oscore_cbor_put_nil(&buffer, &rem_size);
78 }
79 ret += oscore_cbor_put_unsigned(&buffer, &rem_size, alg);
80 ret += oscore_cbor_put_text(&buffer,
81 &rem_size,
82 (const char *)type->s,
83 type->length);
84 ret += oscore_cbor_put_unsigned(&buffer, &rem_size, out_len);
85 return ret;
86}
87
88uint8_t
89oscore_bytes_equal(uint8_t *a_ptr,
90 uint8_t a_len,
91 uint8_t *b_ptr,
92 uint8_t b_len) {
93 if (a_len != b_len) {
94 return 0;
95 }
96
97 if (memcmp(a_ptr, b_ptr, a_len) == 0) {
98 return 1;
99 } else {
100 return 0;
101 }
102}
103
104static void
105oscore_enter_context(coap_context_t *c_context, oscore_ctx_t *osc_ctx) {
106 if (c_context->p_osc_ctx) {
107 oscore_ctx_t *head = c_context->p_osc_ctx;
108 oscore_ctx_t *prev = head;
109 oscore_ctx_t *next = head->next;
110
111 /* verify if oscore context is already attached */
112 if (head == osc_ctx) {
113 return;
114 }
115 while (next != head) {
116 if (next == osc_ctx) {
117 return;
118 }
119 prev = next;
120 next = next->next;
121 }
122 prev->next = osc_ctx;
123 osc_ctx->next = head;
124 } else {
125 c_context->p_osc_ctx = osc_ctx;
126 osc_ctx->next = osc_ctx;
127 }
128}
129
130static void
131oscore_free_recipient(oscore_recipient_ctx_t *recipient) {
132 if (recipient == NULL)
133 return;
134 /* remove recipient from oscore context chain if attached */
135 if (recipient->osc_ctx) {
136 if (recipient->osc_ctx->recipient_chain == recipient) {
137 recipient->osc_ctx->recipient_chain = recipient->next_recipient;
138 } else {
140
141 while (prev && prev->next_recipient != recipient) {
142 prev = prev->next_recipient;
143 }
144 if (prev) {
145 prev->next_recipient = recipient->next_recipient;
146 }
147 }
148 }
149
153}
154
155void
157
158 if (snd_ctx == NULL)
159 return;
163}
164
165void
167 if (osc_ctx == NULL)
168 return;
169
171
172 while (osc_ctx->recipient_chain) {
174
175 oscore_free_recipient(osc_ctx->recipient_chain);
176 osc_ctx->recipient_chain = next;
177 }
178
184}
185
186void
188 while (c_context->p_osc_ctx) {
189 oscore_ctx_t *osc_ctx = c_context->p_osc_ctx;
190
191 if (osc_ctx->next == osc_ctx) {
192 c_context->p_osc_ctx = NULL;
193 } else {
194 oscore_ctx_t *tail = osc_ctx;
195 c_context->p_osc_ctx = osc_ctx->next;
196 while (tail->next != osc_ctx) {
197 tail = tail->next;
198 }
199 tail->next = c_context->p_osc_ctx;
200 }
201 osc_ctx->next = NULL;
202
203 oscore_free_context(osc_ctx);
204 }
205}
206
207int
209 oscore_ctx_t *head = c_context->p_osc_ctx;
210 oscore_ctx_t *prev;
211 oscore_ctx_t *next;
212
213 if (head == NULL)
214 return 0;
215
216 prev = head;
217 next = head;
218 do {
219 if (next == osc_ctx) {
220 if (next->next == next) {
221 c_context->p_osc_ctx = NULL;
222 } else {
223 while (prev->next != next) {
224 prev = prev->next;
225 }
226 prev->next = next->next;
227 if (next == c_context->p_osc_ctx)
228 c_context->p_osc_ctx = next->next;
229 }
230 next->next = NULL;
231 oscore_free_context(osc_ctx);
232 return 1;
233 }
234 next = next->next;
235 } while (next != head);
236 return 0;
237}
238
239/*
240 * oscore_find_context
241 * Finds OSCORE context for rcpkey_id and optional ctxkey_id
242 * rcpkey_id can be 0 length.
243 * Updates recipient_ctx.
244 */
247 const coap_bin_const_t rcpkey_id,
248 const coap_bin_const_t *ctxkey_id,
249 uint8_t *oscore_r2,
250 oscore_recipient_ctx_t **recipient_ctx) {
251 oscore_ctx_t *pt = session->context->p_osc_ctx;
252
253 *recipient_ctx = NULL;
254 assert(rcpkey_id.length == 0 || rcpkey_id.s != NULL);
255 if (pt == NULL)
256 return NULL;
257 do {
258 int ok = 0;
260
261 while (rpt) {
262 ok = 0;
263 if (rpt->recipient_id && rcpkey_id.length == rpt->recipient_id->length) {
264 if (rcpkey_id.length != 0)
265 ok = memcmp(rpt->recipient_id->s, rcpkey_id.s, rcpkey_id.length) != 0;
266 if (oscore_r2) {
267 if (pt->id_context != NULL && pt->id_context->length > 8) {
268 ok = ok + (memcmp(pt->id_context->s, oscore_r2, 8) != 0);
269 } else {
270 ok += 1;
271 }
272 } else if (ctxkey_id) {
273 if (pt->id_context != NULL) {
274 if (ctxkey_id->length != pt->id_context->length)
275 ok += 1;
276 else
277 ok = ok + (memcmp(pt->id_context->s,
278 ctxkey_id->s,
279 ctxkey_id->length) != 0);
280 } else if (ctxkey_id->length > 0)
281 ok += 1;
282 }
283 if (ok == 0) {
284 /* optional id context and recipient id are the same */
285 *recipient_ctx = rpt;
286 return pt; /* OSCORE context found */
287 }
288 }
289 rpt = rpt->next_recipient;
290 } /* while rpt */
291 pt = pt->next;
292 } while (pt != session->context->p_osc_ctx);
293 return NULL;
294}
295
296#define OSCORE_LOG_SIZE 16
297void
299 const char *name,
300 coap_bin_const_t *value) {
301 size_t i;
302
303 if (value == NULL) {
304 coap_log(level, " %-16s\n", name);
305 return;
306 }
307 if (value->length == 0) {
308 coap_log(level, " %-16s <>\n", name);
309 return;
310 }
311 if (coap_get_log_level() >= level) {
312 for (i = 0; i < value->length; i += OSCORE_LOG_SIZE) {
313 char number[3 * OSCORE_LOG_SIZE + 4];
314
315 oscore_convert_to_hex(&value->s[i],
316 value->length - i > OSCORE_LOG_SIZE ?
317 OSCORE_LOG_SIZE : value->length - i,
318 number,
319 sizeof(number));
320 coap_log(level, " %-16s %s\n", i == 0 ? name : "", number);
321 }
322 }
323}
324
325void
326oscore_log_int_value(coap_log_t level, const char *name, int value) {
327 coap_log(level, " %-16s %2d\n", name, value);
328}
329
330void
331oscore_log_char_value(coap_log_t level, const char *name, const char *value) {
332 coap_log(level, " %-16s %s\n", name, value);
333}
334
335void
336oscore_convert_to_hex(const uint8_t *src,
337 size_t src_len,
338 char *dest,
339 size_t dst_len) {
340 /*
341 * Last output character will be '\000'
342 * (If output undersized, add trailing ... to indicate this.
343 */
344 size_t space = (dst_len - 4) / 3;
345 uint32_t qq;
346
347 for (qq = 0; qq < src_len && qq < space; qq++) {
348 char tmp = src[qq] >> 4;
349 if (tmp > 9)
350 tmp = tmp + 0x61 - 10;
351 else
352 tmp = tmp + 0x30;
353 dest[qq * 3] = tmp;
354 tmp = src[qq] & 0xf;
355 if (tmp > 9)
356 tmp = tmp + 0x61 - 10;
357 else
358 tmp = tmp + 0x30;
359 dest[qq * 3 + 1] = tmp;
360 dest[qq * 3 + 2] = 0x20;
361 }
362 if (qq != src_len) {
363 dest[qq * 3] = '.';
364 dest[qq * 3 + 1] = '.';
365 dest[qq * 3 + 2] = '.';
366 qq++;
367 }
368 dest[qq * 3] = 0;
369}
370
373 coap_bin_const_t *salt,
374 coap_bin_const_t *ikm,
375 cose_alg_t aead_alg,
377 coap_str_const_t *type,
378 size_t out_len) {
379 uint8_t info_buffer[80];
380 size_t info_len;
381 coap_bin_const_t *hkdf;
382 uint8_t *hkdf_tmp = coap_malloc_type(COAP_STRING, out_len);
383
384 if (hkdf_tmp == NULL)
385 return NULL;
386
387 info_len = compose_info(info_buffer,
388 sizeof(info_buffer),
389 aead_alg,
390 id,
391 osc_ctx->id_context,
392 type,
393 out_len);
394 if (info_len == 0 || info_len > sizeof(info_buffer)) {
395 coap_free_type(COAP_STRING, hkdf_tmp);
396 return NULL;
397 }
398
399 oscore_hkdf(osc_ctx->hkdf_alg,
400 salt,
401 ikm,
402 info_buffer,
403 info_len,
404 hkdf_tmp,
405 out_len);
406 hkdf = coap_new_bin_const(hkdf_tmp, out_len);
407 coap_free_type(COAP_STRING, hkdf_tmp);
408 return hkdf;
409}
410
411static void
412oscore_log_context(oscore_ctx_t *osc_ctx, const char *heading) {
413#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_OSCORE
414 (void)osc_ctx;
415 (void)heading;
416#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_OSCORE */
418 char buffer[30];
420 size_t count = 0;
421
422 coap_log_oscore("%s\n", heading);
424 cose_get_alg_name(osc_ctx->aead_alg, buffer,
425 sizeof(buffer)));
427 cose_get_hkdf_alg_name(osc_ctx->hkdf_alg, buffer,
428 sizeof(buffer)));
429 oscore_log_hex_value(COAP_LOG_OSCORE, "ID Context", osc_ctx->id_context);
431 "Master Secret",
432 osc_ctx->master_secret);
433 oscore_log_hex_value(COAP_LOG_OSCORE, "Master Salt", osc_ctx->master_salt);
434 oscore_log_hex_value(COAP_LOG_OSCORE, "Common IV", osc_ctx->common_iv);
436 "Sender ID",
437 osc_ctx->sender_context->sender_id);
439 "Sender Key",
440 osc_ctx->sender_context->sender_key);
441 while (next) {
442 snprintf(buffer, sizeof(buffer), "Recipient ID[%zu]", count);
444 buffer,
445 next->recipient_id);
446 snprintf(buffer, sizeof(buffer), "Recipient Key[%zu]", count);
448 buffer,
449 next->recipient_key);
450 count++;
451 next = next->next_recipient;
452 }
453 }
454#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_OSCORE */
455}
456
457void
458oscore_update_ctx(oscore_ctx_t *osc_ctx, coap_bin_const_t *id_context) {
459 coap_bin_const_t *temp;
460
461 /* Update with new ID Context */
463 osc_ctx->id_context = id_context;
464
465 /* Update sender_key, recipient_key and common_iv */
466 temp = osc_ctx->sender_context->sender_key;
467 osc_ctx->sender_context->sender_key =
468 oscore_build_key(osc_ctx,
469 osc_ctx->master_salt,
470 osc_ctx->master_secret,
471 osc_ctx->aead_alg,
472 osc_ctx->sender_context->sender_id,
473 coap_make_str_const("Key"),
474 cose_key_len(osc_ctx->aead_alg));
475 if (!osc_ctx->sender_context->sender_key)
476 osc_ctx->sender_context->sender_key = temp;
477 else
479 temp = osc_ctx->recipient_chain->recipient_key;
481 oscore_build_key(osc_ctx,
482 osc_ctx->master_salt,
483 osc_ctx->master_secret,
484 osc_ctx->aead_alg,
486 coap_make_str_const("Key"),
487 cose_key_len(osc_ctx->aead_alg));
488 if (!osc_ctx->recipient_chain->recipient_key)
489 osc_ctx->recipient_chain->recipient_key = temp;
490 else
492 temp = osc_ctx->common_iv;
493 osc_ctx->common_iv = oscore_build_key(osc_ctx,
494 osc_ctx->master_salt,
495 osc_ctx->master_secret,
496 osc_ctx->aead_alg,
497 NULL,
499 cose_nonce_len(osc_ctx->aead_alg));
500 if (!osc_ctx->common_iv)
501 osc_ctx->common_iv = temp;
502 else
504
505 oscore_log_context(osc_ctx, "Updated Common context");
506}
507
510 oscore_ctx_t *o_osc_ctx,
511 coap_bin_const_t *sender_id,
512 coap_bin_const_t *recipient_id,
513 coap_bin_const_t *id_context) {
514 oscore_ctx_t *osc_ctx = NULL;
515 oscore_sender_ctx_t *sender_ctx = NULL;
516 coap_oscore_rcp_conf_t *rcp_conf;
517
519 if (osc_ctx == NULL)
520 goto error;
521 memset(osc_ctx, 0, sizeof(oscore_ctx_t));
522
524 if (sender_ctx == NULL)
525 goto error;
526 memset(sender_ctx, 0, sizeof(oscore_sender_ctx_t));
527
528 osc_ctx->sender_context = sender_ctx;
529 if (o_osc_ctx->master_secret)
530 osc_ctx->master_secret =
532 o_osc_ctx->master_secret->length);
533 if (o_osc_ctx->master_salt)
534 osc_ctx->master_salt = coap_new_bin_const(o_osc_ctx->master_salt->s,
535 o_osc_ctx->master_salt->length);
536 osc_ctx->aead_alg = o_osc_ctx->aead_alg;
537 osc_ctx->hkdf_alg = o_osc_ctx->hkdf_alg;
538 if (id_context)
539 osc_ctx->id_context = coap_new_bin_const(id_context->s, id_context->length);
540 osc_ctx->ssn_freq = o_osc_ctx->ssn_freq;
541 osc_ctx->replay_window_size = o_osc_ctx->replay_window_size;
542 osc_ctx->rfc8613_b_1_2 = o_osc_ctx->rfc8613_b_1_2;
543 osc_ctx->rfc8613_b_2 = o_osc_ctx->rfc8613_b_2;
544 osc_ctx->save_seq_num_func = o_osc_ctx->save_seq_num_func;
546
547 if (o_osc_ctx->master_secret) {
548 /* sender_ key */
549 sender_ctx->sender_key = oscore_build_key(osc_ctx,
550 osc_ctx->master_salt,
551 osc_ctx->master_secret,
552 osc_ctx->aead_alg,
553 sender_id,
554 coap_make_str_const("Key"),
555 cose_key_len(osc_ctx->aead_alg));
556 if (!sender_ctx->sender_key)
557 goto error;
558
559 /* common IV */
560 osc_ctx->common_iv = oscore_build_key(osc_ctx,
561 osc_ctx->master_salt,
562 osc_ctx->master_secret,
563 osc_ctx->aead_alg,
564 NULL,
566 cose_nonce_len(osc_ctx->aead_alg));
567 if (!osc_ctx->common_iv)
568 goto error;
569
570 }
571
572 /*
573 * Need to set the last Sender Seq Num based on ssn_freq
574 * The value should only change if there is a change to ssn_freq
575 * and (potentially) be lower than seq, then save_seq_num_func() is
576 * immediately called on next SSN update.
577 */
578 sender_ctx->next_seq = 0;
579 sender_ctx->seq = 0;
580
581 sender_ctx->sender_id = coap_new_bin_const(sender_id->s, sender_id->length);
582
584 if (rcp_conf == NULL)
585 goto error;
586 memset(rcp_conf, 0, sizeof(coap_oscore_rcp_conf_t));
587 rcp_conf->recipient_id = coap_new_bin_const(recipient_id->s, recipient_id->length);
588 if (rcp_conf->recipient_id == NULL)
589 goto error;
590 /* rcp_conf is released in oscore_add_recipient() */
591 if (oscore_add_recipient(osc_ctx, rcp_conf, 0) == NULL)
592 goto error;
593
594 oscore_log_context(osc_ctx, "New Common context");
595 oscore_enter_context(c_context, osc_ctx);
596
597 return osc_ctx;
598
599error:
600 oscore_free_context(osc_ctx);
601 return NULL;
602}
603
605oscore_derive_ctx(coap_context_t *c_context, coap_oscore_conf_t *oscore_conf) {
606 oscore_ctx_t *osc_ctx = NULL;
607 oscore_sender_ctx_t *sender_ctx = NULL;
608 coap_oscore_rcp_conf_t *rcp_conf;
609 int ok;
610
612 if (osc_ctx == NULL)
613 goto error;
614 memset(osc_ctx, 0, sizeof(oscore_ctx_t));
615
617 if (sender_ctx == NULL)
618 goto error;
619 memset(sender_ctx, 0, sizeof(oscore_sender_ctx_t));
620
621 osc_ctx->sender_context = sender_ctx;
622 OSC_MOVE_PTR(osc_ctx->master_secret, oscore_conf->master_secret);
623 OSC_MOVE_PTR(osc_ctx->master_salt, oscore_conf->master_salt);
624 osc_ctx->aead_alg = oscore_conf->aead_alg;
625 osc_ctx->hkdf_alg = oscore_conf->hkdf_alg;
626 OSC_MOVE_PTR(osc_ctx->id_context, oscore_conf->id_context);
627 osc_ctx->ssn_freq = oscore_conf->ssn_freq ? oscore_conf->ssn_freq : 1;
628 osc_ctx->replay_window_size = oscore_conf->replay_window ?
629 oscore_conf->replay_window :
631 osc_ctx->rfc8613_b_1_2 = oscore_conf->rfc8613_b_1_2;
632 osc_ctx->rfc8613_b_2 = oscore_conf->rfc8613_b_2;
633 osc_ctx->save_seq_num_func = oscore_conf->save_seq_num_func;
634 osc_ctx->save_seq_num_func_param = oscore_conf->save_seq_num_func_param;
635
636 if (osc_ctx->master_secret) {
637 /* sender_ key */
638 if (oscore_conf->break_sender_key)
639 /* Interop testing */
640 sender_ctx->sender_key = oscore_build_key(osc_ctx,
641 osc_ctx->master_salt,
642 osc_ctx->master_secret,
643 osc_ctx->aead_alg,
644 oscore_conf->sender->sender_id,
645 coap_make_str_const("BAD"),
646 cose_key_len(osc_ctx->aead_alg));
647 else
648 sender_ctx->sender_key = oscore_build_key(osc_ctx,
649 osc_ctx->master_salt,
650 osc_ctx->master_secret,
651 osc_ctx->aead_alg,
652 oscore_conf->sender->sender_id,
653 coap_make_str_const("Key"),
654 cose_key_len(osc_ctx->aead_alg));
655 if (!sender_ctx->sender_key)
656 goto error;
657
658 /* common IV */
659 osc_ctx->common_iv = oscore_build_key(osc_ctx,
660 osc_ctx->master_salt,
661 osc_ctx->master_secret,
662 osc_ctx->aead_alg,
663 NULL,
665 cose_nonce_len(osc_ctx->aead_alg));
666 if (!osc_ctx->common_iv)
667 goto error;
668
669 }
670
671 /*
672 * Need to set the last Sender Seq Num based on ssn_freq
673 * The value should only change if there is a change to ssn_freq
674 * and (potentially) be lower than seq, then save_seq_num_func() is
675 * immediately called on next SSN update.
676 */
677 sender_ctx->next_seq = oscore_conf->start_seq_num -
678 (oscore_conf->start_seq_num % (oscore_conf->ssn_freq > 0 ? oscore_conf->ssn_freq : 1));
679
680 sender_ctx->seq = oscore_conf->start_seq_num;
681 if (oscore_conf->sender) {
682 OSC_MOVE_PTR(sender_ctx->sender_id, oscore_conf->sender->sender_id);
683 coap_free_type(COAP_STRING, oscore_conf->sender);
684 oscore_conf->sender = NULL;
685 }
686
687 rcp_conf = oscore_conf->recipient_chain;
688 ok = 1;
689 while (rcp_conf) {
690 coap_oscore_rcp_conf_t *rcp_next = rcp_conf->next_recipient;
691
692 /* rcp_conf is released in oscore_add_recipient() */
693 if (oscore_add_recipient(osc_ctx, rcp_conf,
694 oscore_conf->break_recipient_key) == NULL) {
695 coap_log_warn("OSCORE: Failed to add Client ID\n");
696 ok = 0;
697 }
698 rcp_conf = rcp_next;
699 }
700 oscore_conf->recipient_chain = NULL;
701 if (!ok)
702 goto error;
703
704 oscore_log_context(osc_ctx, "Common context");
705
706 oscore_enter_context(c_context, osc_ctx);
707
708 return osc_ctx;
709
710error:
711 oscore_free_context(osc_ctx);
712 return NULL;
713}
714
717 uint32_t break_key) {
718 oscore_recipient_ctx_t *rcp_chain = osc_ctx->recipient_chain;
719 oscore_recipient_ctx_t *rcp_ctx = NULL;
720
721 if (rcp_conf->recipient_id->length > 7) {
722 coap_log_warn("oscore_add_recipient: Maximum size of recipient_id is 7 bytes\n");
723 goto free_rcp_conf;
724 }
725 /* Check this is not a duplicate recipient id */
726 while (rcp_chain) {
727 if (rcp_chain->recipient_id->length == rcp_conf->recipient_id->length &&
728 memcmp(rcp_chain->recipient_id->s, rcp_conf->recipient_id->s,
729 rcp_conf->recipient_id->length) == 0) {
730 goto free_rcp_conf;
731 }
732 rcp_chain = rcp_chain->next_recipient;
733 }
735 sizeof(oscore_recipient_ctx_t));
736 if (rcp_ctx == NULL) {
737 goto free_rcp_conf;
738 }
739 memset(rcp_ctx, 0, sizeof(oscore_recipient_ctx_t));
740
741 if (osc_ctx->master_secret) {
742 if (break_key)
743 /* Interop testing */
744 rcp_ctx->recipient_key = oscore_build_key(osc_ctx,
745 osc_ctx->master_salt,
746 osc_ctx->master_secret,
747 osc_ctx->aead_alg,
748 rcp_conf->recipient_id,
749 coap_make_str_const("BAD"),
750 cose_key_len(osc_ctx->aead_alg));
751 else
752 rcp_ctx->recipient_key = oscore_build_key(osc_ctx,
753 osc_ctx->master_salt,
754 osc_ctx->master_secret,
755 osc_ctx->aead_alg,
756 rcp_conf->recipient_id,
757 coap_make_str_const("Key"),
758 cose_key_len(osc_ctx->aead_alg));
759 if (!rcp_ctx->recipient_key) {
760 goto free_rcp_conf;
761 }
762 }
763 rcp_ctx->silent_server = rcp_conf->silent_server;
764 OSC_MOVE_PTR(rcp_ctx->recipient_id, rcp_conf->recipient_id);
765
766 rcp_ctx->initial_state = 1;
767 rcp_ctx->osc_ctx = osc_ctx;
768
769 rcp_chain = osc_ctx->recipient_chain;
770 rcp_ctx->next_recipient = rcp_chain;
771 osc_ctx->recipient_chain = rcp_ctx;
772 /* Just free rcp_conf as all configured values are now in rcp_ctx */
773 coap_free_type(COAP_STRING, rcp_conf);
774 return rcp_ctx;
775
776free_rcp_conf:
779 return NULL;
780}
781
782int
786 while (next) {
787 if (next->recipient_id->length == rid->length &&
788 memcmp(next->recipient_id->s, rid->s, rid->length) == 0) {
789 if (prev != NULL)
790 prev->next_recipient = next->next_recipient;
791 else
792 osc_ctx->recipient_chain = next->next_recipient;
793 oscore_free_recipient(next);
794 return 1;
795 }
796 prev = next;
797 next = next->next_recipient;
798 }
799 return 0;
800}
801
802void
804 if (association) {
805 coap_delete_pdu_lkd(association->sent_pdu);
806 coap_delete_bin_const(association->token);
807 coap_delete_bin_const(association->aad);
808 coap_delete_bin_const(association->nonce);
809 coap_delete_bin_const(association->partial_iv);
811 coap_free_type(COAP_STRING, association);
812 }
813}
814
815int
817 coap_pdu_t *sent_pdu,
818 coap_bin_const_t *token,
819 oscore_recipient_ctx_t *recipient_ctx,
820 coap_bin_const_t *aad,
821 coap_bin_const_t *nonce,
822 coap_bin_const_t *partial_iv,
823 int is_observe) {
824 oscore_association_t *association;
825
826 association = coap_malloc_type(COAP_STRING, sizeof(oscore_association_t));
827 if (association == NULL)
828 return 0;
829
830 memset(association, 0, sizeof(oscore_association_t));
831 association->recipient_ctx = recipient_ctx;
832 association->is_observe = is_observe;
833 association->just_set_up = 1;
834
835 if (sent_pdu) {
836 size_t size;
837 const uint8_t *data;
838
839 association->sent_pdu = coap_pdu_duplicate_lkd(sent_pdu, session,
840 token->length, token->s, NULL);
841 if (association->sent_pdu == NULL)
842 goto error;
843 if (coap_get_data(sent_pdu, &size, &data)) {
844 coap_add_data(association->sent_pdu, size, data);
845 }
846 }
847 association->token = coap_new_bin_const(token->s, token->length);
848 if (association->token == NULL)
849 goto error;
850
851 if (aad) {
852 association->aad = coap_new_bin_const(aad->s, aad->length);
853 if (association->aad == NULL)
854 goto error;
855 }
856
857 if (nonce) {
858 association->nonce = coap_new_bin_const(nonce->s, nonce->length);
859 if (association->nonce == NULL)
860 goto error;
861 }
862
863 if (partial_iv) {
864 association->partial_iv =
865 coap_new_bin_const(partial_iv->s, partial_iv->length);
866 if (association->partial_iv == NULL)
867 goto error;
868 }
869
870 OSCORE_ASSOCIATIONS_ADD(session->associations, association);
871 return 1;
872
873error:
874 oscore_free_association(association);
875 return 0;
876}
877
880 oscore_association_t *association;
881
882 OSCORE_ASSOCIATIONS_FIND(session->associations, token, association);
883 return association;
884}
885
886int
888 oscore_association_t *association) {
889 if (association) {
890 OSCORE_ASSOCIATIONS_DELETE(session->associations, association);
891 oscore_free_association(association);
892 return 1;
893 }
894 return 0;
895}
896
897void
899 if (session) {
900 oscore_association_t *association;
902
903 OSCORE_ASSOCIATIONS_ITER_SAFE(session->associations, association, tmp) {
904 OSCORE_ASSOCIATIONS_DELETE(session->associations, association);
905 oscore_free_association(association);
906 }
907 session->associations = NULL;
908 }
909}
910
911#else /* ! COAP_OSCORE_SUPPORT */
912
913#ifdef __clang__
914/* Make compilers happy that do not like empty modules. As this function is
915 * never used, we ignore -Wunused-function at the end of compiling this file
916 */
917#pragma GCC diagnostic ignored "-Wunused-function"
918#endif
919static inline void
920dummy(void) {
921}
922
923#endif /* ! COAP_OSCORE_SUPPORT */
Library specific build wrapper for coap_internal.h.
@ COAP_OSCORE_COM
Definition coap_mem.h:55
@ COAP_OSCORE_SEN
Definition coap_mem.h:56
@ COAP_OSCORE_REC
Definition coap_mem.h:57
@ 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
#define COAP_OSCORE_DEFAULT_REPLAY_WINDOW
coap_log_t coap_get_log_level(void)
Get the current logging level.
Definition coap_debug.c:103
#define coap_log_oscore(...)
Definition coap_debug.h:132
coap_log_t
Logging type.
Definition coap_debug.h:56
#define coap_log_warn(...)
Definition coap_debug.h:108
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:290
@ COAP_LOG_OSCORE
Definition coap_debug.h:65
size_t oscore_cbor_put_text(uint8_t **buffer, size_t *buf_size, const char *text, size_t text_len)
size_t oscore_cbor_put_nil(uint8_t **buffer, size_t *buf_size)
size_t oscore_cbor_put_unsigned(uint8_t **buffer, size_t *buf_size, uint64_t value)
size_t oscore_cbor_put_bytes(uint8_t **buffer, size_t *buf_size, const uint8_t *bytes, size_t bytes_len)
size_t oscore_cbor_put_array(uint8_t **buffer, size_t *buf_size, size_t elements)
const char * cose_get_hkdf_alg_name(cose_hkdf_alg_t id, char *buffer, size_t buflen)
size_t cose_nonce_len(cose_alg_t cose_alg)
size_t cose_key_len(cose_alg_t cose_alg)
const char * cose_get_alg_name(cose_alg_t id, char *buffer, size_t buflen)
cose_alg_t
#define OSCORE_ASSOCIATIONS_ITER_SAFE(e, el, rtmp)
void oscore_convert_to_hex(const uint8_t *src, size_t src_len, char *dest, size_t dst_len)
int oscore_delete_association(coap_session_t *session, oscore_association_t *association)
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
void oscore_free_sender(oscore_sender_ctx_t *snd_ctx)
coap_bin_const_t * oscore_build_key(oscore_ctx_t *osc_ctx, coap_bin_const_t *salt, coap_bin_const_t *ikm, cose_alg_t aead_alg, coap_bin_const_t *id, coap_str_const_t *type, size_t out_len)
int oscore_delete_recipient(oscore_ctx_t *osc_ctx, coap_bin_const_t *rid)
#define OSCORE_ASSOCIATIONS_DELETE(r, obj)
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
void oscore_free_context(oscore_ctx_t *osc_ctx)
#define OSCORE_ASSOCIATIONS_ADD(r, obj)
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_free_association(oscore_association_t *association)
int oscore_hkdf(cose_hkdf_alg_t hkdf_alg, coap_bin_const_t *salt, coap_bin_const_t *ikm, uint8_t *info, size_t info_len, uint8_t *okm, size_t okm_len)
Derive the key using HKDF() function.
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)
void oscore_delete_server_associations(coap_session_t *session)
void oscore_log_char_value(coap_log_t level, const char *name, const char *value)
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 oscore_log_int_value(coap_log_t level, const char *name, int value)
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
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_delete_oscore_rcp_conf(coap_oscore_rcp_conf_t *oscore_rcp_conf)
Release all the information associated with the OSCORE complex Recipient configuration.
#define OSCORE_ASSOCIATIONS_FIND(r, k, res)
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)
uint8_t oscore_bytes_equal(uint8_t *a_ptr, uint8_t a_len, uint8_t *b_ptr, uint8_t b_len)
void coap_delete_pdu_lkd(coap_pdu_t *pdu)
Dispose of an CoAP PDU and free off associated storage.
Definition coap_pdu.c:194
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
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
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
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_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
static void dummy(void)
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
The CoAP stack's global state is stored in a coap_context_t object.
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.
int silent_server
1 if server is likely to be silent else 0
coap_bin_const_t * recipient_id
Recipient ID (i.e.
struct coap_oscore_rcp_conf_t * next_recipient
Used to maintain the chain.
coap_bin_const_t * sender_id
Sender ID (i.e.
structure for CoAP PDUs
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
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
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
coap_bin_const_t * token
coap_bin_const_t * master_secret
uint32_t replay_window_size
coap_bin_const_t * common_iv
Derived from Master Secret, Master Salt, and ID Context.
struct oscore_ctx_t * next
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_hkdf_alg_t hkdf_alg
Set to one of COSE_HKDF_ALG_*.
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_bin_const_t * master_salt
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.
oscore_recipient_ctx_t * next_recipient
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.