• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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