1 /*
2    Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
3    file at the top-level directory of this distribution.
4 
5    Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6    http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7    <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8    option. This file may not be copied, modified, or distributed
9    except according to those terms.
10 */
11 
12 #ifndef OPTION_H
13 #define OPTION_H
14 
15 #include <stdint.h>
16 
17 #include "oscore_coap.h"
18 
19 #include "common/byte_array.h"
20 #include "common/oscore_edhoc_error.h"
21 
22 #define OPT_SERIAL_OVERHEAD 5
23 
24 enum o_num {
25 	IF_MATCH = 1,
26 	URI_HOST = 3,
27 	ETAG = 4,
28 	IF_NONE_MATCH = 5,
29 	OBSERVE = 6,
30 	URI_PORT = 7,
31 	LOCATION_PATH = 8,
32 	OSCORE = 9,
33 	URI_PATH = 11,
34 	CONTENT_FORMAT = 12,
35 	MAX_AGE = 14,
36 	URI_QUERY = 15,
37 	ACCEPT = 17,
38 	LOCATION_QUERY = 20,
39 	BLOCK2 = 23,
40 	BLOCK1 = 27,
41 	SIZE2 = 28,
42 	PROXY_URI = 35,
43 	PROXY_SCHEME = 39,
44 	SIZE1 = 60,
45 	ECHO = 252,
46 };
47 
48 enum option_class {
49 	CLASS_U, /*unprotected*/
50 	CLASS_I, /*integrity protected only*/
51 	CLASS_E, /*encrypted and integrity protected*/
52 };
53 
54 /**
55  * @brief   Returns whether the CoAP Option with given `code` is a
56  *          Class E Option (encrypted)
57  * @param   code CoAP Option's code
58  * @return  true if the option is a Class E Option
59  */
60 bool is_class_e(uint16_t code);
61 
62 /**
63  * @brief   Parses the passed options until the payload marker of end of
64  *          array and writes them into @a out.
65  *          Returns the number of parsed options and writes the number of
66  *          bytes consumed into @a offset_out. If @a out is NULL, this function
67  *          doesn't write parsed options, but still returns the number
68  *          of options.
69  * @param   options
70  * @param   out Out-array. Must be at least `num_options(...)` long or NULL.
71  * @param   offset_out Pointer to write byte-length of options into.
72  *          Can be NULL.
73  * @return  err
74  */
75 enum err decode_options(struct byte_array options, struct o_coap_option *out,
76 			uint16_t *offset_out);
77 
78 /**
79  * @brief   Returns the length in bytes of the serialized options
80  *          of given class.
81  * @param   options CoAP Option array containing all options
82  *          (possibly including ones of other classes)
83  * @param   opt_num Number of CoAP options in @a options.
84  * @param   class Class of the options to encode
85  * @return  length in bytes
86  */
87 uint32_t encoded_option_len(struct o_coap_option *options, uint16_t opt_num,
88 			    enum option_class class);
89 
90 /**
91  * @brief   Encodes all options in given array having given class.
92  * @param   options CoAP Option array containing all options
93  *          (possibly including ones of other classes)
94  * @param   opt_num Number of CoAP options in @a options.
95  * @param   class Class of the options to encode
96  * @param   out out-pointer. Must be at least `encoded_option_len(...)`
97  *          bytes long.
98  * @param   out_buf_len the length of of the out buffer
99  * @return  err
100  */
101 enum err encode_options(struct o_coap_option *options, uint16_t opt_num,
102 			enum option_class class, uint8_t *out,
103 			uint32_t out_buf_len);
104 
105 /**
106  * @brief	Checks if an array of options contains a observe option
107  * @param	options pointer to an array of options. This can be an array
108  * 			containing all options of an input CoAP packet, the inner or
109  * 			outer options of an OSCORE packet. This is because the observe
110  * 			option is contained in all of the above collections
111  * @param	options_cnt number of entries in the array
112  */
113 bool is_observe(struct o_coap_option *options, uint8_t options_cnt);
114 
115 /**
116  * @brief Returns the value of OBSERVE option.
117  * @param options Options array.
118  * @param options_cnt Number of entries in the array.
119  * @param output Pointer to byte array which will point to the value buffer.
120  *               Set to NULL if not found.
121  * @return true if found, false if not.
122  */
123 bool get_observe_value(struct o_coap_option *options, uint8_t options_cnt,
124 		       struct byte_array *output);
125 
126 /**
127  * @brief	Saves an ECHO option value to be compared later with an ECHO value
128  * 			received from the client.
129  * @param	dest location to save the ECHO value
130  * @param	options	E options
131  * @param	options_cnt the number of the options
132  * @retval	error code
133  *
134 */
135 enum err cache_echo_val(struct byte_array *dest, struct o_coap_option *options,
136 			uint8_t options_cnt);
137 
138 /**
139  * @brief	Checks if an ECHO value is fresh. It takes a decrypted payload and
140  * 			search in it for an ECHO option. If such is find it compares it
141  * 			to the cached one.
142  * @param	cache_value previously saved ECHO value
143  * @param	decrypted_payload the decrypted payload of the message
144  * @retval	error code
145 */
146 enum err echo_val_is_fresh(struct byte_array *cache_val,
147 			   struct byte_array *decrypted_payload);
148 
149 /**
150  * @brief Parse the decrypted OSCORE payload into code, E-options and original unprotected CoAP payload
151  * @param in_payload: input decrypted payload
152  * @param out_code: pointer to code number of the request
153  * @param out_E_options: output pointer to an array of E-options
154  * @param E_options_cnt: count number of E-options
155  * @param out_o_coap_payload: output pointer original unprotected CoAP payload
156  * @return  err
157  */
158 enum err oscore_decrypted_payload_parser(struct byte_array *in_payload,
159 					 uint8_t *out_code,
160 					 struct o_coap_option *out_E_options,
161 					 uint8_t *E_options_cnt,
162 					 struct byte_array *out_o_coap_payload);
163 
164 /**
165  * @brief Compose URI Path (resource name) from given options array.
166  * Implemented based on RFC7252 section 6.5 (partial compliance limited to the library's needs only).
167  * @param options Options array.
168  * @param options_size Options array size (number of items).
169  * @param uri_path Output pointer to write composed URI Path into.
170  * @param uri_path_size Maximum size of the allocated URI Path buffer (input), actual URI Path length (output).
171  * @return ok or error code
172  */
173 enum err uri_path_create(struct o_coap_option *options, uint32_t options_size,
174 			 uint8_t *uri_path, uint32_t *uri_path_size);
175 
176 #endif
177