libcoap 4.3.5-develop-b61cb76
Loading...
Searching...
No Matches
oscore_cbor.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
46
48
49#if COAP_OSCORE_SUPPORT
50
51#include <string.h>
52
53static void
54util_write_byte(uint8_t **buffer, size_t *buf_size, uint8_t value) {
55 if (*buf_size < 1)
56 return;
57 (*buf_size)--;
58 **buffer = value;
59 (*buffer)++;
60}
61
62size_t
63oscore_cbor_put_nil(uint8_t **buffer, size_t *buf_size) {
64 util_write_byte(buffer, buf_size, 0xF6);
65 return 1;
66}
67
68size_t
69oscore_cbor_put_true(uint8_t **buffer, size_t *buf_size) {
70 util_write_byte(buffer, buf_size, 0xF5);
71 return 1;
72}
73
74size_t
75oscore_cbor_put_false(uint8_t **buffer, size_t *buf_size) {
76 util_write_byte(buffer, buf_size, 0xF4);
77 return 1;
78}
79
80size_t
81oscore_cbor_put_text(uint8_t **buffer,
82 size_t *buf_size,
83 const char *text,
84 size_t text_len) {
85 uint8_t *pt = *buffer;
86 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, text_len);
87 if (*buf_size < text_len)
88 return nb;
89 (*buf_size) -= text_len;
90 *pt = (*pt | 0x60);
91 memcpy(*buffer, text, text_len);
92 (*buffer) += text_len;
93 return nb + text_len;
94}
95
96size_t
97oscore_cbor_put_array(uint8_t **buffer, size_t *buf_size, size_t elements) {
98 uint8_t *pt = *buffer;
99 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, elements);
100 *pt = (*pt | 0x80);
101 return nb;
102}
103
104size_t
105oscore_cbor_put_bytes(uint8_t **buffer,
106 size_t *buf_size,
107 const uint8_t *bytes,
108 size_t bytes_len) {
109 uint8_t *pt = *buffer;
110 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, bytes_len);
111 if (*buf_size < bytes_len)
112 return 0;
113 (*buf_size) -= bytes_len;
114 *pt = (*pt | 0x40);
115 if (bytes_len)
116 memcpy(*buffer, bytes, bytes_len);
117 (*buffer) += bytes_len;
118 return nb + bytes_len;
119}
120
121size_t
122oscore_cbor_put_map(uint8_t **buffer, size_t *buf_size, size_t elements) {
123 uint8_t *pt = *buffer;
124 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, elements);
125 *pt = (*pt | 0xa0);
126 return nb;
127}
128
129size_t
130oscore_cbor_put_number(uint8_t **buffer, size_t *buf_size, int64_t value) {
131 if (value < 0)
132 return oscore_cbor_put_negative(buffer, buf_size, -value);
133 else
134 return oscore_cbor_put_unsigned(buffer, buf_size, value);
135}
136
137size_t
138oscore_cbor_put_simple_value(uint8_t **buffer,
139 size_t *buf_size,
140 uint8_t value) {
141 uint8_t *pt = *buffer;
142 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, value);
143 *pt = (*pt | 0xe0);
144 return nb;
145}
146
147size_t
148oscore_cbor_put_tag(uint8_t **buffer, size_t *buf_size, uint64_t value) {
149 uint8_t *pt = *buffer;
150 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, value);
151 *pt = (*pt | 0xc0);
152 return nb;
153}
154
155size_t
156oscore_cbor_put_negative(uint8_t **buffer, size_t *buf_size, int64_t value) {
157 value--;
158 uint8_t *pt = *buffer;
159 size_t nb = oscore_cbor_put_unsigned(buffer, buf_size, value);
160 *pt = (*pt | 0x20);
161 return nb;
162}
163
164static void
165put_b_f(uint8_t **buffer, uint64_t value, uint8_t nr) {
166 uint8_t *pt = *buffer - 1;
167 uint64_t vv = value;
168 for (int q = nr; q > -1; q--) {
169 (*pt--) = (uint8_t)(vv & 0xff);
170 vv = (vv >> 8);
171 }
172}
173
174size_t
175oscore_cbor_put_unsigned(uint8_t **buffer, size_t *buf_size, uint64_t value) {
176 if (value < 0x18) { /* small value half a byte */
177 if (*buf_size < 1)
178 return 0;
179 (*buf_size)--;
180 (**buffer) = (uint8_t)value;
181 (*buffer)++;
182 return 1;
183 } else if ((value > 0x17) && (value < 0x100)) {
184 /* one byte uint8_t */
185 if (*buf_size < 2)
186 return 0;
187 (*buf_size) -= 2;
188 (**buffer) = (0x18);
189 *buffer = (*buffer) + 2;
190 put_b_f(buffer, value, 0);
191 return 2;
192 } else if ((value > 0xff) && (value < 0x10000)) {
193 /* 2 bytes uint16_t */
194 if (*buf_size < 3)
195 return 0;
196 (*buf_size) -= 3;
197 (**buffer) = (0x19);
198 *buffer = (*buffer) + 3;
199 put_b_f(buffer, value, 1);
200 return 3;
201 } else if ((value > 0xffff) && (value < 0x100000000)) {
202 /* 4 bytes uint32_t */
203 if (*buf_size < 5)
204 return 0;
205 (*buf_size) -= 5;
206 (**buffer) = (0x1a);
207 *buffer = (*buffer) + 5;
208 put_b_f(buffer, value, 3);
209 return 5;
210 } else { /*if(value > 0xffffffff)*/
211 /* 8 bytes uint64_t */
212 if (*buf_size < 9)
213 return 0;
214 (*buf_size) -= 9;
215 (**buffer) = (0x1b);
216 *buffer = (*buffer) + 9;
217 put_b_f(buffer, value, 7);
218 return 9;
219 }
220}
221
222static uint8_t
223get_byte(const uint8_t **buffer, size_t *buf_len) {
224 (void)buf_len;
225 if (*buf_len == 0)
226 return 0;
227 return (*buffer)[0];
228}
229
230static uint8_t
231get_byte_inc(const uint8_t **buffer, size_t *buf_len) {
232 if (*buf_len < 1)
233 return 0;
234 (*buf_len)--;
235 return ((*buffer)++)[0];
236}
237
238uint8_t
239oscore_cbor_get_next_element(const uint8_t **buffer, size_t *buf_len) {
240 uint8_t element = get_byte(buffer, buf_len);
241 return element >> 5;
242}
243
244/* oscore_cbor_get_element_size returns
245 * - size of byte strings of character strings
246 * - size of array
247 * - size of map
248 * - value of unsigned integer
249 */
250
251uint64_t
252oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_len) {
253 uint8_t control = get_byte_inc(buffer, buf_len) & 0x1f;
254 uint64_t size;
255
256 if (control < 0x18) {
257 size = (uint64_t)control;
258 } else {
259 control = control & 0x3;
260 int num = 1 << control;
261 size = 0;
262 size_t getal;
263 for (int i = 0; i < num; i++) {
264 getal = get_byte_inc(buffer, buf_len);
265 size = (size << 8) + getal;
266 }
267 }
268 return size;
269}
270
271uint8_t
272oscore_cbor_elem_contained(const uint8_t *data, size_t *buf_len, uint8_t *end) {
273 const uint8_t *buf = data;
274 uint64_t size = oscore_cbor_get_element_size(&buf, buf_len);
275
276 if (size > 0xffffffff || data + size > end) {
277 coap_log_err("oscore_cbor_elem_contained returns 1 \n");
278 return 1;
279 } else
280 return 0;
281}
282
283int64_t
284oscore_cbor_get_negative_integer(const uint8_t **buffer, size_t *buf_len) {
285 return (int64_t)((uint64_t)(-1) - oscore_cbor_get_element_size(buffer, buf_len));
286}
287
288uint64_t
289oscore_cbor_get_unsigned_integer(const uint8_t **buffer, size_t *buf_len) {
290 return oscore_cbor_get_element_size(buffer, buf_len);
291}
292
293/*
294 * oscore_cbor_get_number
295 *
296 * gets a negative or positive number from data
297 * OK: return 0 ; NOK: return 1
298 */
299uint8_t
300oscore_cbor_get_number(const uint8_t **data, size_t *buf_len, int64_t *value) {
301 uint8_t elem = oscore_cbor_get_next_element(data, buf_len);
302 if (elem == CBOR_UNSIGNED_INTEGER) {
303 *value = oscore_cbor_get_unsigned_integer(data, buf_len);
304 return 0;
305 } else if (elem == CBOR_NEGATIVE_INTEGER) {
306 *value = oscore_cbor_get_negative_integer(data, buf_len);
307 return 0;
308 } else
309 return 1;
310}
311
312/*
313 * oscore_cbor_get_simple_value
314 *
315 * gets a simple value from data
316 * OK: return 0 ; NOK: return 1
317 */
318uint8_t
319oscore_cbor_get_simple_value(const uint8_t **data, size_t *buf_len, uint8_t *value) {
320 uint8_t elem = oscore_cbor_get_next_element(data, buf_len);
321 if (elem == CBOR_SIMPLE_VALUE) {
322 *value = get_byte_inc(data, buf_len) & 0x1f;
323 return 0;
324 } else
325 return 1;
326}
327
328void
329oscore_cbor_get_string(const uint8_t **buffer, size_t *buf_len, char *str, size_t size) {
330 (void)buf_len;
331 for (size_t i = 0; i < size; i++) {
332 *str++ = (char)get_byte_inc(buffer, buf_len);
333 }
334}
335
336void
337oscore_cbor_get_array(const uint8_t **buffer, size_t *buf_len, uint8_t *arr, size_t size) {
338 (void)buf_len;
339 for (size_t i = 0; i < size; i++) {
340 *arr++ = get_byte_inc(buffer, buf_len);
341 }
342}
343
344/* oscore_cbor_get_string_array
345 * fills the the size and the array from the cbor element
346 */
347uint8_t
348oscore_cbor_get_string_array(const uint8_t **data, size_t *buf_len,
349 uint8_t **result,
350 size_t *len) {
351
352 uint8_t elem = oscore_cbor_get_next_element(data, buf_len);
353 *len = oscore_cbor_get_element_size(data, buf_len);
354 if (*len > *buf_len)
355 return 1;
356 *result = NULL;
357 void *rs = coap_malloc_type(COAP_STRING, *len);
358 *result = (uint8_t *)rs;
359 if (elem == CBOR_TEXT_STRING) {
360 oscore_cbor_get_string(data, buf_len, (char *)*result, *len);
361 return 0;
362 } else if (elem == CBOR_BYTE_STRING) {
363 oscore_cbor_get_array(data, buf_len, *result, *len);
364 return 0; /* all is well */
365 } else {
366 free(*result);
367 *result = NULL;
368 return 1; /* failure */
369 }
370}
371
372/* oscore_cbor_skip value
373 * returns number of CBOR bytes
374 */
375static size_t
376oscore_cbor_skip_value(const uint8_t **data, size_t *buf_len) {
377 uint8_t elem = oscore_cbor_get_next_element(data, buf_len);
378 uint8_t control = get_byte(data, buf_len) & 0x1f;
379 uint64_t count = 0; /* number of elements in array or map */
380 size_t nb = 0; /* number of elements in array or map */
381 size_t num = 0; /* number of bytes of length or number */
382 size_t size = 0; /* size of value to be skipped */
383 if (control < 0x18) {
384 num = 1;
385 } else {
386 control = control & 0x3;
387 num = 1 + (1 << control);
388 }
389 switch (elem) {
392 if (*buf_len < num)
393 return 0;
394 *buf_len -= num;
395 *data = *data + num;
396 size = num;
397 break;
398 case CBOR_BYTE_STRING:
399 case CBOR_TEXT_STRING:
400 size = num;
401 size += oscore_cbor_get_element_size(data, buf_len);
402 if (*buf_len < size - num)
403 return 0;
404 *buf_len -= (size - num);
405 (*data) = (*data) + size - num;
406 break;
407 case CBOR_ARRAY:
408 count = oscore_cbor_get_element_size(data, buf_len);
409 size = num;
410 /* Every CBOR array element consumes at least one byte. */
411 if (count > *buf_len)
412 return 0;
413 nb = (size_t)count;
414 for (size_t qq = 0; qq < nb; qq++) {
415 size_t value_size = oscore_cbor_skip_value(data, buf_len);
416
417 if (value_size == 0)
418 return 0;
419 size += value_size;
420 }
421 break;
422 case CBOR_MAP:
423 count = oscore_cbor_get_element_size(data, buf_len);
424 size = num;
425 /* Every CBOR map pair consumes at least two bytes. */
426 if (count > *buf_len / 2)
427 return 0;
428 nb = (size_t)count;
429 for (size_t qq = 0; qq < nb; qq++) {
430 size_t key_size = oscore_cbor_skip_value(data, buf_len);
431 size_t value_size;
432
433 if (key_size == 0)
434 return 0;
435 size += key_size;
436 value_size = oscore_cbor_skip_value(data, buf_len);
437 if (value_size == 0)
438 return 0;
439 size += value_size;
440 }
441 break;
442 case CBOR_TAG:
443 if (*buf_len < 1)
444 return 0;
445 *buf_len -= 1;
446 (*data)++;
447 size = 1;
448 break;
449 default:
450 return 0;
451 break;
452 } /* switch */
453 return size;
454}
455
456/* oscore_cbor_strip value
457 * strips the value of the cbor element into result
458 * and returns size
459 */
460uint8_t
461oscore_cbor_strip_value(const uint8_t **data, size_t *buf_len, uint8_t **result, size_t *len) {
462 const uint8_t *st_data = *data;
463 size_t st_buf_len = *buf_len;
464 size_t size = oscore_cbor_skip_value(data, buf_len);
465
466 *result = NULL;
467 *len = 0;
468 if (size == 0) {
469 *data = st_data;
470 *buf_len = st_buf_len;
471 return 1;
472 }
473 *result = coap_malloc_type(COAP_STRING, size);
474 if (*result == NULL) {
475 *data = st_data;
476 *buf_len = st_buf_len;
477 return 1;
478 }
479 for (size_t qq = 0; qq < size; qq++)
480 (*result)[qq] = st_data[qq];
481 *len = size;
482 return 0;
483}
484
485#else /* ! COAP_OSCORE_SUPPORT */
486
487#ifdef __clang__
488/* Make compilers happy that do not like empty modules. As this function is
489 * never used, we ignore -Wunused-function at the end of compiling this file
490 */
491#pragma GCC diagnostic ignored "-Wunused-function"
492#endif
493static inline void
494dummy(void) {
495}
496
497#endif /* ! COAP_OSCORE_SUPPORT */
Library specific build wrapper for coap_internal.h.
@ 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.
#define NULL
Definition coap_option.h:30
#define coap_log_err(...)
Definition coap_debug.h:102
#define CBOR_BYTE_STRING
Definition oscore_cbor.h:64
size_t oscore_cbor_put_text(uint8_t **buffer, size_t *buf_size, const char *text, size_t text_len)
#define CBOR_TAG
Definition oscore_cbor.h:68
#define CBOR_NEGATIVE_INTEGER
Definition oscore_cbor.h:63
uint64_t oscore_cbor_get_element_size(const uint8_t **buffer, size_t *buf_size)
int64_t oscore_cbor_get_negative_integer(const uint8_t **buffer, size_t *buf_size)
#define CBOR_TEXT_STRING
Definition oscore_cbor.h:65
#define CBOR_SIMPLE_VALUE
Definition oscore_cbor.h:69
size_t oscore_cbor_put_number(uint8_t **buffer, size_t *buf_size, int64_t value)
size_t oscore_cbor_put_simple_value(uint8_t **buffer, size_t *buf_size, uint8_t value)
uint8_t oscore_cbor_get_string_array(const uint8_t **data, size_t *buf_size, uint8_t **result, size_t *len)
#define CBOR_UNSIGNED_INTEGER
Definition oscore_cbor.h:62
uint8_t oscore_cbor_strip_value(const uint8_t **data, size_t *buf_size, uint8_t **result, size_t *len)
size_t oscore_cbor_put_nil(uint8_t **buffer, size_t *buf_size)
void oscore_cbor_get_string(const uint8_t **buffer, size_t *buf_size, char *str, size_t size)
uint8_t oscore_cbor_get_simple_value(const uint8_t **data, size_t *buf_size, uint8_t *value)
size_t oscore_cbor_put_false(uint8_t **buffer, size_t *buf_size)
uint8_t oscore_cbor_get_next_element(const uint8_t **buffer, size_t *buf_size)
size_t oscore_cbor_put_negative(uint8_t **buffer, size_t *buf_size, int64_t value)
size_t oscore_cbor_put_true(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)
void oscore_cbor_get_array(const uint8_t **buffer, size_t *buf_size, uint8_t *arr, size_t size)
uint64_t oscore_cbor_get_unsigned_integer(const uint8_t **buffer, size_t *buf_size)
uint8_t oscore_cbor_elem_contained(const uint8_t *data, size_t *buf_size, uint8_t *end)
uint8_t oscore_cbor_get_number(const uint8_t **data, size_t *buf_size, int64_t *value)
#define CBOR_MAP
Definition oscore_cbor.h:67
#define CBOR_ARRAY
Definition oscore_cbor.h:66
size_t oscore_cbor_put_array(uint8_t **buffer, size_t *buf_size, size_t elements)
size_t oscore_cbor_put_map(uint8_t **buffer, size_t *buf_size, size_t elements)
size_t oscore_cbor_put_tag(uint8_t **buffer, size_t *buf_size, uint64_t value)
static void dummy(void)