1c87c5fbaSopenharmony_ci/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2c87c5fbaSopenharmony_ci
3c87c5fbaSopenharmony_ci/*
4c87c5fbaSopenharmony_ci * Copyright (c) 2018, SICS, RISE AB
5c87c5fbaSopenharmony_ci * All rights reserved.
6c87c5fbaSopenharmony_ci *
7c87c5fbaSopenharmony_ci * Redistribution and use in source and binary forms, with or without
8c87c5fbaSopenharmony_ci * modification, are permitted provided that the following conditions
9c87c5fbaSopenharmony_ci * are met:
10c87c5fbaSopenharmony_ci * 1. Redistributions of source code must retain the above copyright
11c87c5fbaSopenharmony_ci *    notice, this list of conditions and the following disclaimer.
12c87c5fbaSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
13c87c5fbaSopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
14c87c5fbaSopenharmony_ci *    documentation and/or other materials provided with the distribution.
15c87c5fbaSopenharmony_ci * 3. Neither the name of the Institute nor the names of its contributors
16c87c5fbaSopenharmony_ci *    may be used to endorse or promote products derived from this software
17c87c5fbaSopenharmony_ci *    without specific prior written permission.
18c87c5fbaSopenharmony_ci *
19c87c5fbaSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
20c87c5fbaSopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21c87c5fbaSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22c87c5fbaSopenharmony_ci * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
23c87c5fbaSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24c87c5fbaSopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25c87c5fbaSopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26c87c5fbaSopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27c87c5fbaSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28c87c5fbaSopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29c87c5fbaSopenharmony_ci * SUCH DAMAGE.
30c87c5fbaSopenharmony_ci *
31c87c5fbaSopenharmony_ci */
32c87c5fbaSopenharmony_ci
33c87c5fbaSopenharmony_ci/**
34c87c5fbaSopenharmony_ci * @file oscore.c
35c87c5fbaSopenharmony_ci * @brief An implementation of the Object Security for Constrained RESTful
36c87c5fbaSopenharmony_ci * Enviornments (RFC 8613).
37c87c5fbaSopenharmony_ci *
38c87c5fbaSopenharmony_ci * \author Martin Gunnarsson  <martin.gunnarsson@ri.se>
39c87c5fbaSopenharmony_ci * adapted to libcoap and major rewrite
40c87c5fbaSopenharmony_ci *     Peter van der Stok <consultancy@vanderstok.org>
41c87c5fbaSopenharmony_ci *     on request of Fairhair alliance
42c87c5fbaSopenharmony_ci * adapted for libcoap integration
43c87c5fbaSopenharmony_ci *      Jon Shallow <supjps-libcoap@jpshallow.com>
44c87c5fbaSopenharmony_ci *
45c87c5fbaSopenharmony_ci */
46c87c5fbaSopenharmony_ci
47c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h"
48c87c5fbaSopenharmony_ci
49c87c5fbaSopenharmony_ci/* oscore_cs_params
50c87c5fbaSopenharmony_ci * returns cbor array [[param_type], [paramtype, param]]
51c87c5fbaSopenharmony_ci */
52c87c5fbaSopenharmony_ciuint8_t *
53c87c5fbaSopenharmony_cioscore_cs_params(int8_t param, int8_t param_type, size_t *len) {
54c87c5fbaSopenharmony_ci  uint8_t buf[50];
55c87c5fbaSopenharmony_ci  size_t rem_size = sizeof(buf);
56c87c5fbaSopenharmony_ci  uint8_t *pt = buf;
57c87c5fbaSopenharmony_ci
58c87c5fbaSopenharmony_ci  *len = 0;
59c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_array(&pt, &rem_size, 2);
60c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_array(&pt, &rem_size, 1);
61c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_number(&pt, &rem_size, param_type);
62c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_array(&pt, &rem_size, 2);
63c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_number(&pt, &rem_size, param_type);
64c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_number(&pt, &rem_size, param);
65c87c5fbaSopenharmony_ci  uint8_t *result = coap_malloc_type(COAP_STRING, *len);
66c87c5fbaSopenharmony_ci  memcpy(result, buf, *len);
67c87c5fbaSopenharmony_ci  return result;
68c87c5fbaSopenharmony_ci}
69c87c5fbaSopenharmony_ci
70c87c5fbaSopenharmony_ci/* oscore_cs_key_params
71c87c5fbaSopenharmony_ci * returns cbor array [paramtype, param]
72c87c5fbaSopenharmony_ci */
73c87c5fbaSopenharmony_ciuint8_t *
74c87c5fbaSopenharmony_cioscore_cs_key_params(cose_curve_t param, int8_t param_type, size_t *len) {
75c87c5fbaSopenharmony_ci  uint8_t buf[50];
76c87c5fbaSopenharmony_ci  size_t rem_size = sizeof(buf);
77c87c5fbaSopenharmony_ci  uint8_t *pt = buf;
78c87c5fbaSopenharmony_ci
79c87c5fbaSopenharmony_ci  *len = 0;
80c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_array(&pt, &rem_size, 2);
81c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_number(&pt, &rem_size, param_type);
82c87c5fbaSopenharmony_ci  *len += oscore_cbor_put_number(&pt, &rem_size, param);
83c87c5fbaSopenharmony_ci  uint8_t *result = coap_malloc_type(COAP_STRING, *len);
84c87c5fbaSopenharmony_ci  memcpy(result, buf, *len);
85c87c5fbaSopenharmony_ci  return result;
86c87c5fbaSopenharmony_ci}
87c87c5fbaSopenharmony_ci
88c87c5fbaSopenharmony_ci/*
89c87c5fbaSopenharmony_ci * Build the CBOR for external_aad
90c87c5fbaSopenharmony_ci *
91c87c5fbaSopenharmony_ci * external_aad = bstr .cbor aad_array
92c87c5fbaSopenharmony_ci *
93c87c5fbaSopenharmony_ci * No group mode
94c87c5fbaSopenharmony_ci * aad_array = [
95c87c5fbaSopenharmony_ci *   oscore_version : uint,
96c87c5fbaSopenharmony_ci *   algorithms : [ alg_aead : int / tstr ],
97c87c5fbaSopenharmony_ci *   request_kid : bstr,
98c87c5fbaSopenharmony_ci *   request_piv : bstr,
99c87c5fbaSopenharmony_ci *   options : bstr,
100c87c5fbaSopenharmony_ci * ]
101c87c5fbaSopenharmony_ci *
102c87c5fbaSopenharmony_ci * Group mode
103c87c5fbaSopenharmony_ci * aad_array = [
104c87c5fbaSopenharmony_ci *   oscore_version : uint,
105c87c5fbaSopenharmony_ci *   algorithms : [alg_aead : int / tstr / null,
106c87c5fbaSopenharmony_ci *                 alg_signature_enc : int / tstr / null,
107c87c5fbaSopenharmony_ci *                 alg_signature : int / tstr / null,
108c87c5fbaSopenharmony_ci *                 alg_pairwise_key_agreement : int / tstr / null],
109c87c5fbaSopenharmony_ci *   request_kid : bstr,
110c87c5fbaSopenharmony_ci *   request_piv : bstr,
111c87c5fbaSopenharmony_ci *   options : bstr,
112c87c5fbaSopenharmony_ci *   request_kid_context : bstr,
113c87c5fbaSopenharmony_ci *   OSCORE_option: bstr,
114c87c5fbaSopenharmony_ci *   sender_public_key: bstr,        (initiator's key)
115c87c5fbaSopenharmony_ci *   gm_public_key: bstr / null
116c87c5fbaSopenharmony_ci * ]
117c87c5fbaSopenharmony_ci */
118c87c5fbaSopenharmony_cisize_t
119c87c5fbaSopenharmony_cioscore_prepare_e_aad(oscore_ctx_t *ctx,
120c87c5fbaSopenharmony_ci                     cose_encrypt0_t *cose,
121c87c5fbaSopenharmony_ci                     const uint8_t *oscore_option,
122c87c5fbaSopenharmony_ci                     size_t oscore_option_len,
123c87c5fbaSopenharmony_ci                     coap_bin_const_t *sender_public_key,
124c87c5fbaSopenharmony_ci                     uint8_t *external_aad_ptr,
125c87c5fbaSopenharmony_ci                     size_t external_aad_size) {
126c87c5fbaSopenharmony_ci  size_t external_aad_len = 0;
127c87c5fbaSopenharmony_ci  size_t rem_size = external_aad_size;
128c87c5fbaSopenharmony_ci
129c87c5fbaSopenharmony_ci  (void)oscore_option;
130c87c5fbaSopenharmony_ci  (void)oscore_option_len;
131c87c5fbaSopenharmony_ci  (void)sender_public_key;
132c87c5fbaSopenharmony_ci
133c87c5fbaSopenharmony_ci  if (ctx->mode != OSCORE_MODE_SINGLE)
134c87c5fbaSopenharmony_ci    external_aad_len += oscore_cbor_put_array(&external_aad_ptr, &rem_size, 9);
135c87c5fbaSopenharmony_ci  else
136c87c5fbaSopenharmony_ci    external_aad_len += oscore_cbor_put_array(&external_aad_ptr, &rem_size, 5);
137c87c5fbaSopenharmony_ci
138c87c5fbaSopenharmony_ci  /* oscore_version, always "1" */
139c87c5fbaSopenharmony_ci  external_aad_len += oscore_cbor_put_unsigned(&external_aad_ptr, &rem_size, 1);
140c87c5fbaSopenharmony_ci
141c87c5fbaSopenharmony_ci  if (ctx->mode == OSCORE_MODE_SINGLE) {
142c87c5fbaSopenharmony_ci    /* Algoritms array with one item*/
143c87c5fbaSopenharmony_ci    external_aad_len += oscore_cbor_put_array(&external_aad_ptr, &rem_size, 1);
144c87c5fbaSopenharmony_ci    /* Encryption Algorithm   */
145c87c5fbaSopenharmony_ci    external_aad_len +=
146c87c5fbaSopenharmony_ci        oscore_cbor_put_number(&external_aad_ptr, &rem_size, ctx->aead_alg);
147c87c5fbaSopenharmony_ci  }
148c87c5fbaSopenharmony_ci  /* request_kid */
149c87c5fbaSopenharmony_ci  external_aad_len += oscore_cbor_put_bytes(&external_aad_ptr,
150c87c5fbaSopenharmony_ci                                            &rem_size,
151c87c5fbaSopenharmony_ci                                            cose->key_id.s,
152c87c5fbaSopenharmony_ci                                            cose->key_id.length);
153c87c5fbaSopenharmony_ci  /* request_piv */
154c87c5fbaSopenharmony_ci  external_aad_len += oscore_cbor_put_bytes(&external_aad_ptr,
155c87c5fbaSopenharmony_ci                                            &rem_size,
156c87c5fbaSopenharmony_ci                                            cose->partial_iv.s,
157c87c5fbaSopenharmony_ci                                            cose->partial_iv.length);
158c87c5fbaSopenharmony_ci  /* options */
159c87c5fbaSopenharmony_ci  /* Put integrity protected options, at present there are none. */
160c87c5fbaSopenharmony_ci  external_aad_len +=
161c87c5fbaSopenharmony_ci      oscore_cbor_put_bytes(&external_aad_ptr, &rem_size, NULL, 0);
162c87c5fbaSopenharmony_ci
163c87c5fbaSopenharmony_ci  return external_aad_len;
164c87c5fbaSopenharmony_ci}
165c87c5fbaSopenharmony_ci
166c87c5fbaSopenharmony_ci/*
167c87c5fbaSopenharmony_ci * oscore_encode_option_value
168c87c5fbaSopenharmony_ci */
169c87c5fbaSopenharmony_cisize_t
170c87c5fbaSopenharmony_cioscore_encode_option_value(uint8_t *option_buffer,
171c87c5fbaSopenharmony_ci                           size_t option_buf_len,
172c87c5fbaSopenharmony_ci                           cose_encrypt0_t *cose,
173c87c5fbaSopenharmony_ci                           uint8_t group_flag,
174c87c5fbaSopenharmony_ci                           uint8_t appendix_b_2) {
175c87c5fbaSopenharmony_ci  size_t offset = 1;
176c87c5fbaSopenharmony_ci  size_t rem_space = option_buf_len;
177c87c5fbaSopenharmony_ci
178c87c5fbaSopenharmony_ci  (void)group_flag;
179c87c5fbaSopenharmony_ci  if (cose->partial_iv.length > 5) {
180c87c5fbaSopenharmony_ci    return 0;
181c87c5fbaSopenharmony_ci  }
182c87c5fbaSopenharmony_ci  option_buffer[0] = 0;
183c87c5fbaSopenharmony_ci
184c87c5fbaSopenharmony_ci  if (cose->partial_iv.length > 0 && cose->partial_iv.length <= 5 &&
185c87c5fbaSopenharmony_ci      cose->partial_iv.s != NULL) {
186c87c5fbaSopenharmony_ci    option_buffer[0] |= (0x07 & cose->partial_iv.length);
187c87c5fbaSopenharmony_ci    memcpy(&(option_buffer[offset]),
188c87c5fbaSopenharmony_ci           cose->partial_iv.s,
189c87c5fbaSopenharmony_ci           cose->partial_iv.length);
190c87c5fbaSopenharmony_ci    offset += cose->partial_iv.length;
191c87c5fbaSopenharmony_ci    assert(rem_space > cose->partial_iv.length);
192c87c5fbaSopenharmony_ci    rem_space -= cose->partial_iv.length;
193c87c5fbaSopenharmony_ci  }
194c87c5fbaSopenharmony_ci
195c87c5fbaSopenharmony_ci  if (cose->kid_context.length > 0 && cose->kid_context.s != NULL) {
196c87c5fbaSopenharmony_ci    if (appendix_b_2) {
197c87c5fbaSopenharmony_ci      /* Need to CBOR wrap kid_context - yuk! */
198c87c5fbaSopenharmony_ci      uint8_t *ptr = &option_buffer[offset+1];
199c87c5fbaSopenharmony_ci
200c87c5fbaSopenharmony_ci      option_buffer[0] |= 0x10;
201c87c5fbaSopenharmony_ci      option_buffer[offset] = (uint8_t)oscore_cbor_put_bytes(&ptr, &rem_space,
202c87c5fbaSopenharmony_ci                                                             cose->kid_context.s,
203c87c5fbaSopenharmony_ci                                                             cose->kid_context.length);
204c87c5fbaSopenharmony_ci      offset += option_buffer[offset] + 1;
205c87c5fbaSopenharmony_ci    } else {
206c87c5fbaSopenharmony_ci      option_buffer[0] |= 0x10;
207c87c5fbaSopenharmony_ci      option_buffer[offset] = (uint8_t)cose->kid_context.length;
208c87c5fbaSopenharmony_ci      offset++;
209c87c5fbaSopenharmony_ci      memcpy(&(option_buffer[offset]),
210c87c5fbaSopenharmony_ci             cose->kid_context.s,
211c87c5fbaSopenharmony_ci             (uint8_t)cose->kid_context.length);
212c87c5fbaSopenharmony_ci      offset += cose->kid_context.length;
213c87c5fbaSopenharmony_ci      assert(rem_space > cose->kid_context.length);
214c87c5fbaSopenharmony_ci      rem_space -= cose->kid_context.length;
215c87c5fbaSopenharmony_ci    }
216c87c5fbaSopenharmony_ci  }
217c87c5fbaSopenharmony_ci
218c87c5fbaSopenharmony_ci  if (cose->key_id.s != NULL) {
219c87c5fbaSopenharmony_ci    option_buffer[0] |= 0x08;
220c87c5fbaSopenharmony_ci    if (cose->key_id.length) {
221c87c5fbaSopenharmony_ci      memcpy(&(option_buffer[offset]), cose->key_id.s, cose->key_id.length);
222c87c5fbaSopenharmony_ci      offset += cose->key_id.length;
223c87c5fbaSopenharmony_ci      assert(rem_space > cose->key_id.length);
224c87c5fbaSopenharmony_ci      rem_space -= cose->key_id.length;
225c87c5fbaSopenharmony_ci    }
226c87c5fbaSopenharmony_ci  }
227c87c5fbaSopenharmony_ci
228c87c5fbaSopenharmony_ci  if (offset == 1 && option_buffer[0] == 0) {
229c87c5fbaSopenharmony_ci    /* If option_value is 0x00 it should be empty. */
230c87c5fbaSopenharmony_ci    offset = 0;
231c87c5fbaSopenharmony_ci  }
232c87c5fbaSopenharmony_ci  assert(offset <= option_buf_len);
233c87c5fbaSopenharmony_ci  cose->oscore_option.s = option_buffer;
234c87c5fbaSopenharmony_ci  cose->oscore_option.length = offset;
235c87c5fbaSopenharmony_ci  return offset;
236c87c5fbaSopenharmony_ci}
237c87c5fbaSopenharmony_ci
238c87c5fbaSopenharmony_ci/*
239c87c5fbaSopenharmony_ci * oscore_decode_option_value
240c87c5fbaSopenharmony_ci * error: return 0
241c87c5fbaSopenharmony_ci * OK: return 1
242c87c5fbaSopenharmony_ci *
243c87c5fbaSopenharmony_ci * Basic assupmption is that all is preset to 0 or NULL on entry
244c87c5fbaSopenharmony_ci */
245c87c5fbaSopenharmony_ciint
246c87c5fbaSopenharmony_cioscore_decode_option_value(const uint8_t *opt_value,
247c87c5fbaSopenharmony_ci                           size_t option_len,
248c87c5fbaSopenharmony_ci                           cose_encrypt0_t *cose) {
249c87c5fbaSopenharmony_ci  uint8_t partial_iv_len = (opt_value[0] & 0x07);
250c87c5fbaSopenharmony_ci  size_t offset = 1;
251c87c5fbaSopenharmony_ci
252c87c5fbaSopenharmony_ci  cose->oscore_option.s = opt_value;
253c87c5fbaSopenharmony_ci  cose->oscore_option.length = option_len;
254c87c5fbaSopenharmony_ci
255c87c5fbaSopenharmony_ci  if (option_len == 0)
256c87c5fbaSopenharmony_ci    return 1; /* empty option */
257c87c5fbaSopenharmony_ci
258c87c5fbaSopenharmony_ci  if (option_len > 255 || partial_iv_len == 6 || partial_iv_len == 7 ||
259c87c5fbaSopenharmony_ci      (opt_value[0] & 0xC0) != 0) {
260c87c5fbaSopenharmony_ci    return 0;
261c87c5fbaSopenharmony_ci  }
262c87c5fbaSopenharmony_ci
263c87c5fbaSopenharmony_ci  if ((opt_value[0] & 0x20) != 0) {
264c87c5fbaSopenharmony_ci    return 0;
265c87c5fbaSopenharmony_ci  }
266c87c5fbaSopenharmony_ci
267c87c5fbaSopenharmony_ci  if (partial_iv_len != 0) {
268c87c5fbaSopenharmony_ci    coap_bin_const_t partial_iv;
269c87c5fbaSopenharmony_ci    if (offset + partial_iv_len > option_len) {
270c87c5fbaSopenharmony_ci      return 0;
271c87c5fbaSopenharmony_ci    }
272c87c5fbaSopenharmony_ci    partial_iv.s = &(opt_value[offset]);
273c87c5fbaSopenharmony_ci    partial_iv.length = partial_iv_len;
274c87c5fbaSopenharmony_ci    cose_encrypt0_set_partial_iv(cose, &partial_iv);
275c87c5fbaSopenharmony_ci    offset += partial_iv_len;
276c87c5fbaSopenharmony_ci  }
277c87c5fbaSopenharmony_ci
278c87c5fbaSopenharmony_ci  if ((opt_value[0] & 0x10) != 0) {
279c87c5fbaSopenharmony_ci    coap_bin_const_t kid_context;
280c87c5fbaSopenharmony_ci
281c87c5fbaSopenharmony_ci    if (offset >= option_len)
282c87c5fbaSopenharmony_ci      return 0;
283c87c5fbaSopenharmony_ci    kid_context.length = opt_value[offset];
284c87c5fbaSopenharmony_ci    offset++;
285c87c5fbaSopenharmony_ci    if (offset + kid_context.length > option_len) {
286c87c5fbaSopenharmony_ci      return 0;
287c87c5fbaSopenharmony_ci    }
288c87c5fbaSopenharmony_ci    kid_context.s = &(opt_value[offset]);
289c87c5fbaSopenharmony_ci    cose_encrypt0_set_kid_context(cose, &kid_context);
290c87c5fbaSopenharmony_ci    offset = offset + kid_context.length;
291c87c5fbaSopenharmony_ci  }
292c87c5fbaSopenharmony_ci
293c87c5fbaSopenharmony_ci  if ((opt_value[0] & 0x08) != 0) {
294c87c5fbaSopenharmony_ci    coap_bin_const_t key_id;
295c87c5fbaSopenharmony_ci
296c87c5fbaSopenharmony_ci    key_id.length = option_len - offset;
297c87c5fbaSopenharmony_ci    if ((int)key_id.length < 0) {
298c87c5fbaSopenharmony_ci      return 0;
299c87c5fbaSopenharmony_ci    }
300c87c5fbaSopenharmony_ci    key_id.s = &(opt_value[offset]);
301c87c5fbaSopenharmony_ci    cose_encrypt0_set_key_id(cose, &key_id);
302c87c5fbaSopenharmony_ci  }
303c87c5fbaSopenharmony_ci  return 1;
304c87c5fbaSopenharmony_ci}
305c87c5fbaSopenharmony_ci
306c87c5fbaSopenharmony_ci/*
307c87c5fbaSopenharmony_ci * oscore_prepare_aad
308c87c5fbaSopenharmony_ci *
309c87c5fbaSopenharmony_ci * Creates and sets External AAD for encryption
310c87c5fbaSopenharmony_ci */
311c87c5fbaSopenharmony_cisize_t
312c87c5fbaSopenharmony_cioscore_prepare_aad(const uint8_t *external_aad_buffer,
313c87c5fbaSopenharmony_ci                   size_t external_aad_len,
314c87c5fbaSopenharmony_ci                   uint8_t *aad_buffer,
315c87c5fbaSopenharmony_ci                   size_t aad_size) {
316c87c5fbaSopenharmony_ci  size_t ret = 0;
317c87c5fbaSopenharmony_ci  size_t rem_size = aad_size;
318c87c5fbaSopenharmony_ci  char encrypt0[] = "Encrypt0";
319c87c5fbaSopenharmony_ci
320c87c5fbaSopenharmony_ci  (void)aad_size; /* TODO */
321c87c5fbaSopenharmony_ci  /* Creating the AAD */
322c87c5fbaSopenharmony_ci  ret += oscore_cbor_put_array(&aad_buffer, &rem_size, 3);
323c87c5fbaSopenharmony_ci  /* 1. "Encrypt0" */
324c87c5fbaSopenharmony_ci  ret +=
325c87c5fbaSopenharmony_ci      oscore_cbor_put_text(&aad_buffer, &rem_size, encrypt0, strlen(encrypt0));
326c87c5fbaSopenharmony_ci  /* 2. Empty h'' entry */
327c87c5fbaSopenharmony_ci  ret += oscore_cbor_put_bytes(&aad_buffer, &rem_size, NULL, 0);
328c87c5fbaSopenharmony_ci  /* 3. External AAD */
329c87c5fbaSopenharmony_ci  ret += oscore_cbor_put_bytes(&aad_buffer,
330c87c5fbaSopenharmony_ci                               &rem_size,
331c87c5fbaSopenharmony_ci                               external_aad_buffer,
332c87c5fbaSopenharmony_ci                               external_aad_len);
333c87c5fbaSopenharmony_ci
334c87c5fbaSopenharmony_ci  return ret;
335c87c5fbaSopenharmony_ci}
336c87c5fbaSopenharmony_ci
337c87c5fbaSopenharmony_ci/*
338c87c5fbaSopenharmony_ci * oscore_generate_nonce
339c87c5fbaSopenharmony_ci *
340c87c5fbaSopenharmony_ci * Creates Nonce
341c87c5fbaSopenharmony_ci */
342c87c5fbaSopenharmony_civoid
343c87c5fbaSopenharmony_cioscore_generate_nonce(cose_encrypt0_t *ptr,
344c87c5fbaSopenharmony_ci                      oscore_ctx_t *ctx,
345c87c5fbaSopenharmony_ci                      uint8_t *buffer,
346c87c5fbaSopenharmony_ci                      uint8_t size) {
347c87c5fbaSopenharmony_ci  memset(buffer, 0, size);
348c87c5fbaSopenharmony_ci  buffer[0] = (uint8_t)(ptr->key_id.length);
349c87c5fbaSopenharmony_ci  memcpy(&(buffer[((size - 5) - ptr->key_id.length)]),
350c87c5fbaSopenharmony_ci         ptr->key_id.s,
351c87c5fbaSopenharmony_ci         ptr->key_id.length);
352c87c5fbaSopenharmony_ci  memcpy(&(buffer[size - ptr->partial_iv.length]),
353c87c5fbaSopenharmony_ci         ptr->partial_iv.s,
354c87c5fbaSopenharmony_ci         ptr->partial_iv.length);
355c87c5fbaSopenharmony_ci  for (int i = 0; i < size; i++) {
356c87c5fbaSopenharmony_ci    buffer[i] = buffer[i] ^ (uint8_t)ctx->common_iv->s[i];
357c87c5fbaSopenharmony_ci  }
358c87c5fbaSopenharmony_ci}
359c87c5fbaSopenharmony_ci
360c87c5fbaSopenharmony_ci/*
361c87c5fbaSopenharmony_ci * oscore_validate_sender_seq
362c87c5fbaSopenharmony_ci *
363c87c5fbaSopenharmony_ci * Return 1 if OK, 0 otherwise
364c87c5fbaSopenharmony_ci */
365c87c5fbaSopenharmony_ciuint8_t
366c87c5fbaSopenharmony_cioscore_validate_sender_seq(oscore_recipient_ctx_t *ctx, cose_encrypt0_t *cose) {
367c87c5fbaSopenharmony_ci  uint64_t incoming_seq =
368c87c5fbaSopenharmony_ci      coap_decode_var_bytes8(cose->partial_iv.s, cose->partial_iv.length);
369c87c5fbaSopenharmony_ci
370c87c5fbaSopenharmony_ci  if (incoming_seq >= OSCORE_SEQ_MAX) {
371c87c5fbaSopenharmony_ci    coap_log_warn("OSCORE Replay protection, SEQ larger than SEQ_MAX.\n");
372c87c5fbaSopenharmony_ci    return 0;
373c87c5fbaSopenharmony_ci  }
374c87c5fbaSopenharmony_ci
375c87c5fbaSopenharmony_ci  ctx->rollback_last_seq = ctx->last_seq;
376c87c5fbaSopenharmony_ci  ctx->rollback_sliding_window = ctx->sliding_window;
377c87c5fbaSopenharmony_ci
378c87c5fbaSopenharmony_ci  /* Special case since we do not use unsigned int for seq */
379c87c5fbaSopenharmony_ci  if (ctx->initial_state == 1) {
380c87c5fbaSopenharmony_ci    ctx->initial_state = 0;
381c87c5fbaSopenharmony_ci    /* bitfield. B0 biggest seq seen.  B1 seq-1 seen, B2 seq-2 seen etc. */
382c87c5fbaSopenharmony_ci    ctx->sliding_window = 1;
383c87c5fbaSopenharmony_ci    ctx->last_seq = incoming_seq;
384c87c5fbaSopenharmony_ci  } else if (incoming_seq > ctx->last_seq) {
385c87c5fbaSopenharmony_ci    /* Update the replay window */
386c87c5fbaSopenharmony_ci    uint64_t shift = incoming_seq - ctx->last_seq;
387c87c5fbaSopenharmony_ci    ctx->sliding_window = ctx->sliding_window << shift;
388c87c5fbaSopenharmony_ci    /* bitfield. B0 biggest seq seen.  B1 seq-1 seen, B2 seq-2 seen etc. */
389c87c5fbaSopenharmony_ci    ctx->sliding_window |= 1;
390c87c5fbaSopenharmony_ci    ctx->last_seq = incoming_seq;
391c87c5fbaSopenharmony_ci  } else if (incoming_seq == ctx->last_seq) {
392c87c5fbaSopenharmony_ci    coap_log_warn("OSCORE: Replay protection, replayed SEQ (%" PRIu64 ")\n",
393c87c5fbaSopenharmony_ci                  incoming_seq);
394c87c5fbaSopenharmony_ci    return 0;
395c87c5fbaSopenharmony_ci  } else { /* incoming_seq < last_seq */
396c87c5fbaSopenharmony_ci    uint64_t shift = ctx->last_seq - incoming_seq - 1;
397c87c5fbaSopenharmony_ci    uint64_t pattern;
398c87c5fbaSopenharmony_ci
399c87c5fbaSopenharmony_ci    if (shift > ctx->osc_ctx->replay_window_size || shift > 63) {
400c87c5fbaSopenharmony_ci      coap_log_warn("OSCORE: Replay protection, SEQ outside of replay window (%"
401c87c5fbaSopenharmony_ci                    PRIu64 " %" PRIu64 ")\n",
402c87c5fbaSopenharmony_ci                    ctx->last_seq,
403c87c5fbaSopenharmony_ci                    incoming_seq);
404c87c5fbaSopenharmony_ci      return 0;
405c87c5fbaSopenharmony_ci    }
406c87c5fbaSopenharmony_ci    /* seq + replay_window_size > last_seq */
407c87c5fbaSopenharmony_ci    pattern = 1ULL << shift;
408c87c5fbaSopenharmony_ci    if (ctx->sliding_window & pattern) {
409c87c5fbaSopenharmony_ci      coap_log_warn("OSCORE: Replay protection, replayed SEQ (%" PRIu64 ")\n",
410c87c5fbaSopenharmony_ci                    incoming_seq);
411c87c5fbaSopenharmony_ci      return 0;
412c87c5fbaSopenharmony_ci    }
413c87c5fbaSopenharmony_ci    /* bitfield. B0 biggest seq seen.  B1 seq-1 seen, B2 seq-2 seen etc. */
414c87c5fbaSopenharmony_ci    ctx->sliding_window |= pattern;
415c87c5fbaSopenharmony_ci  }
416c87c5fbaSopenharmony_ci  coap_log_oscore("OSCORE: window 0x%" PRIx64 " seq-B0 %" PRIu64 " SEQ %"
417c87c5fbaSopenharmony_ci                  PRIu64 "\n",
418c87c5fbaSopenharmony_ci                  ctx->sliding_window,
419c87c5fbaSopenharmony_ci                  ctx->last_seq,
420c87c5fbaSopenharmony_ci                  incoming_seq);
421c87c5fbaSopenharmony_ci  return 1;
422c87c5fbaSopenharmony_ci}
423c87c5fbaSopenharmony_ci
424c87c5fbaSopenharmony_ci/*
425c87c5fbaSopenharmony_ci * oscore_increment_sender_seq
426c87c5fbaSopenharmony_ci *
427c87c5fbaSopenharmony_ci * Return 0 if SEQ MAX, return 1 if OK
428c87c5fbaSopenharmony_ci */
429c87c5fbaSopenharmony_ciuint8_t
430c87c5fbaSopenharmony_cioscore_increment_sender_seq(oscore_ctx_t *ctx) {
431c87c5fbaSopenharmony_ci  ctx->sender_context->seq++;
432c87c5fbaSopenharmony_ci
433c87c5fbaSopenharmony_ci  if (ctx->sender_context->seq >= OSCORE_SEQ_MAX) {
434c87c5fbaSopenharmony_ci    return 0;
435c87c5fbaSopenharmony_ci  } else {
436c87c5fbaSopenharmony_ci    return 1;
437c87c5fbaSopenharmony_ci  }
438c87c5fbaSopenharmony_ci}
439c87c5fbaSopenharmony_ci
440c87c5fbaSopenharmony_ci/*
441c87c5fbaSopenharmony_ci * oscore_roll_back_seq
442c87c5fbaSopenharmony_ci *
443c87c5fbaSopenharmony_ci * Restore the sequence number and replay-window to the previous state. This
444c87c5fbaSopenharmony_ci * is to be used when decryption fail.
445c87c5fbaSopenharmony_ci */
446c87c5fbaSopenharmony_civoid
447c87c5fbaSopenharmony_cioscore_roll_back_seq(oscore_recipient_ctx_t *ctx) {
448c87c5fbaSopenharmony_ci
449c87c5fbaSopenharmony_ci  if (ctx->rollback_sliding_window != 0) {
450c87c5fbaSopenharmony_ci    ctx->sliding_window = ctx->rollback_sliding_window;
451c87c5fbaSopenharmony_ci    ctx->rollback_sliding_window = 0;
452c87c5fbaSopenharmony_ci  }
453c87c5fbaSopenharmony_ci  if (ctx->rollback_last_seq != 0) {
454c87c5fbaSopenharmony_ci    ctx->last_seq = ctx->rollback_last_seq;
455c87c5fbaSopenharmony_ci    ctx->rollback_last_seq = 0;
456c87c5fbaSopenharmony_ci  }
457c87c5fbaSopenharmony_ci}
458