libcoap 4.3.5-develop-72190a8
Loading...
Searching...
No Matches
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 * 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/* oscore_cs_params
50 * returns cbor array [[param_type], [paramtype, param]]
51 */
52uint8_t *
53oscore_cs_params(int8_t param, int8_t param_type, size_t *len) {
54 uint8_t buf[50];
55 size_t rem_size = sizeof(buf);
56 uint8_t *pt = buf;
57
58 *len = 0;
59 *len += oscore_cbor_put_array(&pt, &rem_size, 2);
60 *len += oscore_cbor_put_array(&pt, &rem_size, 1);
61 *len += oscore_cbor_put_number(&pt, &rem_size, param_type);
62 *len += oscore_cbor_put_array(&pt, &rem_size, 2);
63 *len += oscore_cbor_put_number(&pt, &rem_size, param_type);
64 *len += oscore_cbor_put_number(&pt, &rem_size, param);
65 uint8_t *result = coap_malloc_type(COAP_STRING, *len);
66 memcpy(result, buf, *len);
67 return result;
68}
69
70/* oscore_cs_key_params
71 * returns cbor array [paramtype, param]
72 */
73uint8_t *
74oscore_cs_key_params(cose_curve_t param, int8_t param_type, size_t *len) {
75 uint8_t buf[50];
76 size_t rem_size = sizeof(buf);
77 uint8_t *pt = buf;
78
79 *len = 0;
80 *len += oscore_cbor_put_array(&pt, &rem_size, 2);
81 *len += oscore_cbor_put_number(&pt, &rem_size, param_type);
82 *len += oscore_cbor_put_number(&pt, &rem_size, param);
83 uint8_t *result = coap_malloc_type(COAP_STRING, *len);
84 memcpy(result, buf, *len);
85 return result;
86}
87
88/*
89 * Build the CBOR for external_aad
90 *
91 * external_aad = bstr .cbor aad_array
92 *
93 * No group mode
94 * aad_array = [
95 * oscore_version : uint,
96 * algorithms : [ alg_aead : int / tstr ],
97 * request_kid : bstr,
98 * request_piv : bstr,
99 * options : bstr,
100 * ]
101 *
102 * Group mode
103 * aad_array = [
104 * oscore_version : uint,
105 * algorithms : [alg_aead : int / tstr / null,
106 * alg_signature_enc : int / tstr / null,
107 * alg_signature : int / tstr / null,
108 * alg_pairwise_key_agreement : int / tstr / null],
109 * request_kid : bstr,
110 * request_piv : bstr,
111 * options : bstr,
112 * request_kid_context : bstr,
113 * OSCORE_option: bstr,
114 * sender_public_key: bstr, (initiator's key)
115 * gm_public_key: bstr / null
116 * ]
117 */
118size_t
120 cose_encrypt0_t *cose,
121 const uint8_t *oscore_option,
122 size_t oscore_option_len,
123 coap_bin_const_t *sender_public_key,
124 uint8_t *external_aad_ptr,
125 size_t external_aad_size) {
126 size_t external_aad_len = 0;
127 size_t rem_size = external_aad_size;
128
129 (void)oscore_option;
130 (void)oscore_option_len;
131 (void)sender_public_key;
132
133 if (ctx->mode != OSCORE_MODE_SINGLE)
134 external_aad_len += oscore_cbor_put_array(&external_aad_ptr, &rem_size, 9);
135 else
136 external_aad_len += oscore_cbor_put_array(&external_aad_ptr, &rem_size, 5);
137
138 /* oscore_version, always "1" */
139 external_aad_len += oscore_cbor_put_unsigned(&external_aad_ptr, &rem_size, 1);
140
141 if (ctx->mode == OSCORE_MODE_SINGLE) {
142 /* Algoritms array with one item*/
143 external_aad_len += oscore_cbor_put_array(&external_aad_ptr, &rem_size, 1);
144 /* Encryption Algorithm */
145 external_aad_len +=
146 oscore_cbor_put_number(&external_aad_ptr, &rem_size, ctx->aead_alg);
147 }
148 /* request_kid */
149 external_aad_len += oscore_cbor_put_bytes(&external_aad_ptr,
150 &rem_size,
151 cose->key_id.s,
152 cose->key_id.length);
153 /* request_piv */
154 external_aad_len += oscore_cbor_put_bytes(&external_aad_ptr,
155 &rem_size,
156 cose->partial_iv.s,
157 cose->partial_iv.length);
158 /* options */
159 /* Put integrity protected options, at present there are none. */
160 external_aad_len +=
161 oscore_cbor_put_bytes(&external_aad_ptr, &rem_size, NULL, 0);
162
163 return external_aad_len;
164}
165
166/*
167 * oscore_encode_option_value
168 */
169size_t
170oscore_encode_option_value(uint8_t *option_buffer,
171 size_t option_buf_len,
172 cose_encrypt0_t *cose,
173 uint8_t group_flag,
174 uint8_t appendix_b_2) {
175 size_t offset = 1;
176 size_t rem_space = option_buf_len;
177
178 (void)group_flag;
179 if (cose->partial_iv.length > 5) {
180 return 0;
181 }
182 option_buffer[0] = 0;
183
184 if (cose->partial_iv.length > 0 && cose->partial_iv.length <= 5 &&
185 cose->partial_iv.s != NULL) {
186 option_buffer[0] |= (0x07 & cose->partial_iv.length);
187 memcpy(&(option_buffer[offset]),
188 cose->partial_iv.s,
189 cose->partial_iv.length);
190 offset += cose->partial_iv.length;
191 assert(rem_space > cose->partial_iv.length);
192 rem_space -= cose->partial_iv.length;
193 }
194
195 if (cose->kid_context.length > 0 && cose->kid_context.s != NULL) {
196 if (appendix_b_2) {
197 /* Need to CBOR wrap kid_context - yuk! */
198 uint8_t *ptr = &option_buffer[offset+1];
199
200 option_buffer[0] |= 0x10;
201 option_buffer[offset] = (uint8_t)oscore_cbor_put_bytes(&ptr, &rem_space,
202 cose->kid_context.s,
203 cose->kid_context.length);
204 offset += option_buffer[offset] + 1;
205 } else {
206 option_buffer[0] |= 0x10;
207 option_buffer[offset] = (uint8_t)cose->kid_context.length;
208 offset++;
209 memcpy(&(option_buffer[offset]),
210 cose->kid_context.s,
211 (uint8_t)cose->kid_context.length);
212 offset += cose->kid_context.length;
213 assert(rem_space > cose->kid_context.length);
214 rem_space -= cose->kid_context.length;
215 }
216 }
217
218 if (cose->key_id.s != NULL) {
219 option_buffer[0] |= 0x08;
220 if (cose->key_id.length) {
221 memcpy(&(option_buffer[offset]), cose->key_id.s, cose->key_id.length);
222 offset += cose->key_id.length;
223 assert(rem_space > cose->key_id.length);
224 rem_space -= cose->key_id.length;
225 }
226 }
227
228 if (offset == 1 && option_buffer[0] == 0) {
229 /* If option_value is 0x00 it should be empty. */
230 offset = 0;
231 }
232 assert(offset <= option_buf_len);
233 cose->oscore_option.s = option_buffer;
234 cose->oscore_option.length = offset;
235 return offset;
236}
237
238/*
239 * oscore_decode_option_value
240 * error: return 0
241 * OK: return 1
242 *
243 * Basic assupmption is that all is preset to 0 or NULL on entry
244 */
245int
246oscore_decode_option_value(const uint8_t *opt_value,
247 size_t option_len,
248 cose_encrypt0_t *cose) {
249 uint8_t partial_iv_len = (opt_value[0] & 0x07);
250 size_t offset = 1;
251
252 cose->oscore_option.s = opt_value;
253 cose->oscore_option.length = option_len;
254
255 if (option_len == 0)
256 return 1; /* empty option */
257
258 if (option_len > 255 || partial_iv_len == 6 || partial_iv_len == 7 ||
259 (opt_value[0] & 0xC0) != 0) {
260 return 0;
261 }
262
263 if ((opt_value[0] & 0x20) != 0) {
264 return 0;
265 }
266
267 if (partial_iv_len != 0) {
268 coap_bin_const_t partial_iv;
269 if (offset + partial_iv_len > option_len) {
270 return 0;
271 }
272 partial_iv.s = &(opt_value[offset]);
273 partial_iv.length = partial_iv_len;
274 cose_encrypt0_set_partial_iv(cose, &partial_iv);
275 offset += partial_iv_len;
276 }
277
278 if ((opt_value[0] & 0x10) != 0) {
279 coap_bin_const_t kid_context;
280
281 if (offset >= option_len)
282 return 0;
283 kid_context.length = opt_value[offset];
284 offset++;
285 if (offset + kid_context.length > option_len) {
286 return 0;
287 }
288 kid_context.s = &(opt_value[offset]);
289 cose_encrypt0_set_kid_context(cose, &kid_context);
290 offset = offset + kid_context.length;
291 }
292
293 if ((opt_value[0] & 0x08) != 0) {
294 coap_bin_const_t key_id;
295
296 key_id.length = option_len - offset;
297 if ((int)key_id.length < 0) {
298 return 0;
299 }
300 key_id.s = &(opt_value[offset]);
301 cose_encrypt0_set_key_id(cose, &key_id);
302 }
303 return 1;
304}
305
306/*
307 * oscore_prepare_aad
308 *
309 * Creates and sets External AAD for encryption
310 */
311size_t
312oscore_prepare_aad(const uint8_t *external_aad_buffer,
313 size_t external_aad_len,
314 uint8_t *aad_buffer,
315 size_t aad_size) {
316 size_t ret = 0;
317 size_t rem_size = aad_size;
318 char encrypt0[] = "Encrypt0";
319
320 (void)aad_size; /* TODO */
321 /* Creating the AAD */
322 ret += oscore_cbor_put_array(&aad_buffer, &rem_size, 3);
323 /* 1. "Encrypt0" */
324 ret +=
325 oscore_cbor_put_text(&aad_buffer, &rem_size, encrypt0, strlen(encrypt0));
326 /* 2. Empty h'' entry */
327 ret += oscore_cbor_put_bytes(&aad_buffer, &rem_size, NULL, 0);
328 /* 3. External AAD */
329 ret += oscore_cbor_put_bytes(&aad_buffer,
330 &rem_size,
331 external_aad_buffer,
332 external_aad_len);
333
334 return ret;
335}
336
337/*
338 * oscore_generate_nonce
339 *
340 * Creates Nonce
341 */
342void
344 oscore_ctx_t *ctx,
345 uint8_t *buffer,
346 uint8_t size) {
347 memset(buffer, 0, size);
348 buffer[0] = (uint8_t)(ptr->key_id.length);
349 memcpy(&(buffer[((size - 5) - ptr->key_id.length)]),
350 ptr->key_id.s,
351 ptr->key_id.length);
352 memcpy(&(buffer[size - ptr->partial_iv.length]),
353 ptr->partial_iv.s,
354 ptr->partial_iv.length);
355 for (int i = 0; i < size; i++) {
356 buffer[i] = buffer[i] ^ (uint8_t)ctx->common_iv->s[i];
357 }
358}
359
360/*
361 * oscore_validate_sender_seq
362 *
363 * Return 1 if OK, 0 otherwise
364 */
365uint8_t
367 uint64_t incoming_seq =
369
370 if (incoming_seq >= OSCORE_SEQ_MAX) {
371 coap_log_warn("OSCORE Replay protection, SEQ larger than SEQ_MAX.\n");
372 return 0;
373 }
374
375 ctx->rollback_last_seq = ctx->last_seq;
377
378 /* Special case since we do not use unsigned int for seq */
379 if (ctx->initial_state == 1) {
380 ctx->initial_state = 0;
381 /* bitfield. B0 biggest seq seen. B1 seq-1 seen, B2 seq-2 seen etc. */
382 ctx->sliding_window = 1;
383 ctx->last_seq = incoming_seq;
384 } else if (incoming_seq > ctx->last_seq) {
385 /* Update the replay window */
386 uint64_t shift = incoming_seq - ctx->last_seq;
387 ctx->sliding_window = ctx->sliding_window << shift;
388 /* bitfield. B0 biggest seq seen. B1 seq-1 seen, B2 seq-2 seen etc. */
389 ctx->sliding_window |= 1;
390 ctx->last_seq = incoming_seq;
391 } else if (incoming_seq == ctx->last_seq) {
392 coap_log_warn("OSCORE: Replay protection, replayed SEQ (%" PRIu64 ")\n",
393 incoming_seq);
394 return 0;
395 } else { /* incoming_seq < last_seq */
396 uint64_t shift = ctx->last_seq - incoming_seq - 1;
397 uint64_t pattern;
398
399 if (shift > ctx->osc_ctx->replay_window_size || shift > 63) {
400 coap_log_warn("OSCORE: Replay protection, SEQ outside of replay window (%"
401 PRIu64 " %" PRIu64 ")\n",
402 ctx->last_seq,
403 incoming_seq);
404 return 0;
405 }
406 /* seq + replay_window_size > last_seq */
407 pattern = 1ULL << shift;
408 if (ctx->sliding_window & pattern) {
409 coap_log_warn("OSCORE: Replay protection, replayed SEQ (%" PRIu64 ")\n",
410 incoming_seq);
411 return 0;
412 }
413 /* bitfield. B0 biggest seq seen. B1 seq-1 seen, B2 seq-2 seen etc. */
414 ctx->sliding_window |= pattern;
415 }
416 coap_log_oscore("OSCORE: window 0x%" PRIx64 " seq-B0 %" PRIu64 " SEQ %"
417 PRIu64 "\n",
418 ctx->sliding_window,
419 ctx->last_seq,
420 incoming_seq);
421 return 1;
422}
423
424/*
425 * oscore_increment_sender_seq
426 *
427 * Return 0 if SEQ MAX, return 1 if OK
428 */
429uint8_t
431 ctx->sender_context->seq++;
432
433 if (ctx->sender_context->seq >= OSCORE_SEQ_MAX) {
434 return 0;
435 } else {
436 return 1;
437 }
438}
439
440/*
441 * oscore_roll_back_seq
442 *
443 * Restore the sequence number and replay-window to the previous state. This
444 * is to be used when decryption fail.
445 */
446void
448
449 if (ctx->rollback_sliding_window != 0) {
452 }
453 if (ctx->rollback_last_seq != 0) {
454 ctx->last_seq = ctx->rollback_last_seq;
455 ctx->rollback_last_seq = 0;
456 }
457}
#define PRIx64
#define PRIu64
Library specific build wrapper for coap_internal.h.
@ COAP_STRING
Definition coap_mem.h:39
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.
uint64_t coap_decode_var_bytes8(const uint8_t *buf, size_t len)
Decodes multiple-length byte sequences.
Definition coap_encode.c:67
#define coap_log_oscore(...)
Definition coap_debug.h:126
#define coap_log_warn(...)
Definition coap_debug.h:102
size_t oscore_cbor_put_text(uint8_t **buffer, size_t *buf_size, const char *text, size_t text_len)
Definition oscore_cbor.c:77
size_t oscore_cbor_put_number(uint8_t **buffer, size_t *buf_size, int64_t value)
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)
Definition oscore_cbor.c:92
void cose_encrypt0_set_kid_context(cose_encrypt0_t *ptr, coap_bin_const_t *kid_context)
cose_curve_t
Definition oscore_cose.h:60
void cose_encrypt0_set_partial_iv(cose_encrypt0_t *ptr, coap_bin_const_t *partial_iv)
void cose_encrypt0_set_key_id(cose_encrypt0_t *ptr, coap_bin_const_t *key_id)
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
uint8_t oscore_validate_sender_seq(oscore_recipient_ctx_t *ctx, cose_encrypt0_t *cose)
Definition oscore.c:366
#define OSCORE_SEQ_MAX
int oscore_decode_option_value(const uint8_t *opt_value, size_t option_len, cose_encrypt0_t *cose)
Definition oscore.c:246
uint8_t oscore_increment_sender_seq(oscore_ctx_t *ctx)
Definition oscore.c:430
void oscore_roll_back_seq(oscore_recipient_ctx_t *ctx)
Definition oscore.c:447
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
uint8_t * oscore_cs_key_params(cose_curve_t param, int8_t param_type, size_t *len)
Definition oscore.c:74
void oscore_generate_nonce(cose_encrypt0_t *ptr, oscore_ctx_t *ctx, uint8_t *buffer, uint8_t size)
Definition oscore.c:343
uint8_t * oscore_cs_params(int8_t param, int8_t param_type, size_t *len)
Definition oscore.c:53
@ OSCORE_MODE_SINGLE
Vanilla RFC8613 support.
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_bin_const_t partial_iv
coap_bin_const_t kid_context
coap_bin_const_t key_id
coap_bin_const_t oscore_option
uint32_t replay_window_size
coap_bin_const_t * common_iv
Derived from Master Secret, Master Salt, and ID Context.
oscore_mode_t mode
oscore_sender_ctx_t * sender_context
cose_alg_t aead_alg