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