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