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 33 /** 34 * @file oscore_context.h 35 * @brief An implementation of the Object Security for Constrained RESTful 36 * Enviornments (RFC 8613). 37 * 38 * \author 39 * Martin Gunnarsson <martin.gunnarsson@ri.se> 40 * adapted to libcoap; added group communication 41 * Peter van der Stok <consultancy@vanderstok.org> 42 * on request of Fairhair alliance 43 * adapted for libcoap integration 44 * Jon Shallow <supjps-libcoap@jpshallow.com> 45 * 46 */ 47 48 #ifndef _OSCORE_CONTEXT_H 49 #define _OSCORE_CONTEXT_H 50 51 #include "coap3/coap_internal.h" 52 #include "coap3/coap_uthash_internal.h" 53 #include <stdint.h> 54 55 /** 56 * @ingroup internal_api 57 * @addtogroup oscore_internal 58 * @{ 59 */ 60 61 #define CONTEXT_KEY_LEN 16 62 #define TOKEN_SEQ_NUM 2 /* to be set by application */ 63 #define EP_CTX_NUM 10 /* to be set by application */ 64 #define CONTEXT_INIT_VECT_LEN 13 65 #define CONTEXT_SEQ_LEN sizeof(uint64_t) 66 67 #define ED25519_PRIVATE_KEY_LEN 32 68 #define ED25519_PUBLIC_KEY_LEN 32 69 #define ED25519_SEED_LEN 32 70 #define ED25519_SIGNATURE_LEN 64 71 72 #define OSCORE_SEQ_MAX (((uint64_t)1 << 40) - 1) 73 74 typedef enum { 75 OSCORE_MODE_SINGLE = 0, /**< Vanilla RFC8613 support */ 76 OSCORE_MODE_GROUP, /**< TODO draft-ietf-core-oscore-groupcomm */ 77 OSCORE_MODE_PAIRWISE /**< TODO draft-ietf-core-oscore-groupcomm */ 78 } oscore_mode_t; 79 80 typedef struct oscore_sender_ctx_t oscore_sender_ctx_t; 81 typedef struct oscore_recipient_ctx_t oscore_recipient_ctx_t; 82 typedef struct oscore_association_t oscore_association_t; 83 84 struct oscore_ctx_t { 85 struct oscore_ctx_t *next; 86 coap_bin_const_t *master_secret; 87 coap_bin_const_t *master_salt; 88 coap_bin_const_t *common_iv; /**< Derived from Master Secret, 89 Master Salt, and ID Context */ 90 coap_bin_const_t *id_context; /**< contains GID in case of group */ 91 oscore_sender_ctx_t *sender_context; 92 oscore_recipient_ctx_t *recipient_chain; 93 cose_alg_t aead_alg; 94 cose_hkdf_alg_t hkdf_alg; 95 oscore_mode_t mode; 96 uint8_t rfc8613_b_1_2; /**< 1 if rfc8613 B.1.2 enabled else 0 */ 97 uint8_t rfc8613_b_2; /**< 1 if rfc8613 B.2 protocol else 0 */ 98 uint32_t ssn_freq; /**< Sender Seq Num update frequency */ 99 uint32_t replay_window_size; 100 coap_oscore_save_seq_num_t save_seq_num_func; /**< Called every seq num 101 change */ 102 void *save_seq_num_func_param; /**< Passed to save_seq_num_func() */ 103 }; 104 105 struct oscore_sender_ctx_t { 106 uint64_t seq; 107 uint64_t next_seq; /**< Used for ssn_freq updating */ 108 coap_bin_const_t *sender_key; 109 coap_bin_const_t *sender_id; 110 }; 111 112 struct oscore_recipient_ctx_t { 113 /* This field allows recipient chaining */ 114 oscore_recipient_ctx_t *next_recipient; 115 oscore_ctx_t *osc_ctx; 116 uint64_t last_seq; 117 /* uint64_t highest_seq; */ 118 uint64_t sliding_window; 119 uint64_t rollback_sliding_window; 120 uint64_t rollback_last_seq; 121 coap_bin_const_t *recipient_key; 122 coap_bin_const_t *recipient_id; 123 uint8_t echo_value[8]; 124 uint8_t initial_state; 125 }; 126 127 #define OSCORE_ASSOCIATIONS_ADD(r, obj) \ 128 HASH_ADD(hh, (r), token->s[0], (obj)->token->length, (obj)) 129 130 #define OSCORE_ASSOCIATIONS_DELETE(r, obj) HASH_DELETE(hh, (r), (obj)) 131 132 #define OSCORE_ASSOCIATIONS_ITER(r, tmp) \ 133 oscore_associations_t *tmp, *rtmp; \ 134 HASH_ITER (hh, (r), tmp, rtmp) 135 136 #define OSCORE_ASSOCIATIONS_ITER_SAFE(e, el, rtmp) \ 137 for ((el) = (e); (el) && ((rtmp) = (el)->hh.next, 1); (el) = (rtmp)) 138 139 #define OSCORE_ASSOCIATIONS_FIND(r, k, res) \ 140 { HASH_FIND(hh, (r), (k)->s, (k)->length, (res)); } 141 142 struct oscore_association_t { 143 UT_hash_handle hh; 144 oscore_recipient_ctx_t *recipient_ctx; 145 coap_pdu_t *sent_pdu; 146 coap_bin_const_t *token; 147 coap_bin_const_t *aad; 148 coap_bin_const_t *nonce; 149 coap_bin_const_t *partial_iv; 150 coap_tick_t last_seen; 151 uint8_t is_observe; 152 }; 153 154 /** 155 * oscore_derive_ctx - derive a osc_ctx from oscore_conf information 156 * 157 * @param c_context The CoAP context to associate OSCORE context with. 158 * @param oscore_conf The OSCORE configuration to use. 159 * 160 * @return NULL if failure or derived OSCORE context linked onto 161 * @p c_context chain. 162 */ 163 oscore_ctx_t *oscore_derive_ctx(coap_context_t *c_context, 164 coap_oscore_conf_t *oscore_conf); 165 166 /** 167 * oscore_duplicate_ctx - duplicate a osc_ctx 168 * 169 * @param c_context The CoAP context to associate OSCORE context with. 170 * @param o_osc_ctx The OSCORE context to duplicate. 171 * @param sender_id The Sender ID to use in the duplication. 172 * @param recipient_id The Recipient ID to use in the duplication. 173 * @param id_context The Context ID to use in the duplicate. 174 * 175 * @return NULL if failure or duplicated OSCORE context linked onto 176 * @p c_context chain. 177 */ 178 oscore_ctx_t *oscore_duplicate_ctx(coap_context_t *c_context, 179 oscore_ctx_t *o_osc_ctx, 180 coap_bin_const_t *sender_id, 181 coap_bin_const_t *recipient_id, 182 coap_bin_const_t *id_context); 183 184 /** 185 * oscore_update_ctx - update a osc_ctx with a new id_context 186 * 187 * @param osc_ctx The OSCORE context to update. 188 * @param id_context The Context ID to use in the duplicate. 189 */ 190 void oscore_update_ctx(oscore_ctx_t *osc_ctx, coap_bin_const_t *id_context); 191 192 void oscore_free_context(oscore_ctx_t *osc_ctx); 193 194 void oscore_free_contexts(coap_context_t *c_context); 195 196 int oscore_remove_context(coap_context_t *c_context, oscore_ctx_t *osc_ctx); 197 198 /** 199 * oscore_add_recipient - add in recipient information 200 * 201 * @param ctx The OSCORE context to add to. 202 * @param rid The recipient ID. 203 * @param break_key @c 1 if testing for broken keys, else @c 0. 204 * 205 * @return NULL if failure or recipient context linked onto @p ctx chain. 206 */ 207 oscore_recipient_ctx_t *oscore_add_recipient(oscore_ctx_t *ctx, 208 coap_bin_const_t *rid, 209 uint32_t break_key); 210 211 int oscore_delete_recipient(oscore_ctx_t *osc_ctx, coap_bin_const_t *rid); 212 213 uint8_t oscore_bytes_equal(uint8_t *a_ptr, 214 uint8_t a_len, 215 uint8_t *b_ptr, 216 uint8_t b_len); 217 218 void oscore_convert_to_hex(const uint8_t *src, 219 size_t src_len, 220 char *dest, 221 size_t dst_len); 222 223 void oscore_log_hex_value(coap_log_t level, 224 const char *name, 225 coap_bin_const_t *value); 226 227 void oscore_log_int_value(coap_log_t level, const char *name, int value); 228 229 void oscore_log_char_value(coap_log_t level, const char *name, 230 const char *value); 231 232 /** 233 * oscore_find_context - Locate recipient context (and hence OSCORE context) 234 * 235 * @param c_context The CoAP COntext to search. 236 * @param rcpkey_id The Recipient kid. 237 * @param ctxkey_id The ID Context to match (or NULL if no check). 238 * @param oscore_r2 Partial id_context to match against or NULL. 239 * @param recipient_ctx The recipient context to update. 240 * 241 * return The OSCORE context and @p recipient_ctx updated, or NULL is error. 242 */ 243 oscore_ctx_t *oscore_find_context(const coap_context_t *c_context, 244 const coap_bin_const_t rcpkey_id, 245 const coap_bin_const_t *ctxkey_id, 246 uint8_t *oscore_r2, 247 oscore_recipient_ctx_t **recipient_ctx); 248 249 void oscore_free_association(oscore_association_t *association); 250 251 int oscore_new_association(coap_session_t *session, 252 coap_pdu_t *sent_pdu, 253 coap_bin_const_t *token, 254 oscore_recipient_ctx_t *recipient_ctx, 255 coap_bin_const_t *aad, 256 coap_bin_const_t *nonce, 257 coap_bin_const_t *partial_iv, 258 int is_observe); 259 260 oscore_association_t *oscore_find_association(coap_session_t *session, 261 coap_bin_const_t *token); 262 263 int oscore_delete_association(coap_session_t *session, 264 oscore_association_t *association); 265 266 void oscore_delete_server_associations(coap_session_t *session); 267 268 int oscore_derive_keystream(oscore_ctx_t *osc_ctx, 269 cose_encrypt0_t *code, 270 uint8_t coap_request, 271 coap_bin_const_t *sender_key, 272 coap_bin_const_t *id_context, 273 size_t cs_size, 274 uint8_t *keystream, 275 size_t keystream_size); 276 277 /** @} */ 278 279 #endif /* _OSCORE_CONTEXT_H */ 280