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