Branch data Line data Source code
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 : : #include <string.h>
13 : :
14 : : #include "oscore/option.h"
15 : : #include "oscore/oscore_coap.h"
16 : :
17 : : #include "common/memcpy_s.h"
18 : :
19 : : /**
20 : : * @brief Securely append a substring to given buffer.
21 : : *
22 : : * @param buffer Buffer to have the substring appended.
23 : : * @param current_size Current size of the buffer content. Updated after successfull append.
24 : : * @param max_size Memory size allocated for the buffer.
25 : : * @param substring Substring buffer to be appended.
26 : : * @param substring_size Substring size.
27 : : * @return ok or error
28 : : */
29 : 28 : static enum err buffer_append(uint8_t *buffer, uint32_t *current_size,
30 : : uint32_t max_size, const uint8_t *substring,
31 : : uint32_t substring_size)
32 : : {
33 : 28 : uint8_t *destination =
34 : 28 : &buffer[*current_size]; //pointer to current end of the content
35 : 28 : uint32_t remaining_size =
36 : : max_size -
37 : 28 : (*current_size); //how many bytes in the buffer are still available
38 [ - + ]: 28 : TRY(_memcpy_s(destination, remaining_size, substring, substring_size));
39 : 28 : *current_size += substring_size;
40 : 28 : return ok;
41 : : }
42 : :
43 : 37 : bool is_class_e(uint16_t code)
44 : : {
45 : : // blacklist, because OSCORE dictates that unknown options SHALL be processed as class E
46 : : // RFC 9668 Section 3.1: EDHOC option (21) is Class U for OSCORE
47 [ + + + + : 33 : return code != URI_HOST && code != URI_PORT && code != OSCORE &&
+ + ]
48 [ + + + + : 70 : code != PROXY_URI && code != PROXY_SCHEME && code != EDHOC;
+ - ]
49 : : }
50 : :
51 : 24 : bool is_observe(struct o_coap_option *options, uint8_t options_cnt)
52 : : {
53 [ + + ]: 32 : for (uint8_t i = 0; i < options_cnt; i++) {
54 [ + + ]: 14 : if (options[i].option_number == OBSERVE) {
55 : 6 : return true;
56 : : }
57 : : }
58 : 18 : return false;
59 : : }
60 : :
61 : 41 : bool get_observe_value(struct o_coap_option *options, uint8_t options_cnt,
62 : : struct byte_array *output)
63 : : {
64 [ + - - + ]: 41 : if ((NULL == options) || (NULL == output)) {
65 : 0 : return false;
66 : : }
67 : :
68 [ + + ]: 79 : for (uint8_t i = 0; i < options_cnt; i++) {
69 [ + + ]: 44 : if (OBSERVE != options[i].option_number) {
70 : 38 : continue;
71 : : }
72 : :
73 : 6 : output->ptr = options[i].value;
74 : 6 : output->len = options[i].len;
75 : 6 : return true;
76 : : }
77 : 35 : output = NULL;
78 : 35 : return false;
79 : : }
80 : :
81 : 6 : enum err cache_echo_val(struct byte_array *dest, struct o_coap_option *options,
82 : : uint8_t options_cnt)
83 : : {
84 [ + + ]: 12 : for (uint8_t i = 0; i < options_cnt; i++) {
85 [ + + ]: 10 : if (options[i].option_number == ECHO) {
86 : 4 : PRINT_MSG("Caching the ECHO value!\n");
87 [ - + ]: 4 : TRY(_memcpy_s(dest->ptr, dest->len, options[i].value,
88 : : options[i].len));
89 : 4 : dest->len = options[i].len;
90 : 4 : return ok;
91 : : }
92 : : }
93 : 2 : return no_echo_option;
94 : : }
95 : :
96 : 18 : enum err oscore_decrypted_payload_parser(struct byte_array *in_payload,
97 : : uint8_t *out_code,
98 : : struct o_coap_option *out_E_options,
99 : : uint8_t *E_options_cnt,
100 : : struct byte_array *out_o_coap_payload)
101 : : {
102 : 18 : uint8_t *temp_payload_ptr = in_payload->ptr;
103 : 18 : uint32_t temp_payload_len = in_payload->len;
104 : :
105 : : /* Code */
106 : 18 : *out_code = *(temp_payload_ptr++);
107 : 18 : temp_payload_len--;
108 : :
109 : 18 : struct byte_array remaining_bytes =
110 : : BYTE_ARRAY_INIT(temp_payload_ptr, temp_payload_len);
111 [ - + ]: 18 : TRY(options_deserialize(&remaining_bytes, out_E_options, E_options_cnt,
112 : : out_o_coap_payload));
113 : :
114 : 18 : return ok;
115 : : }
116 : :
117 : 5 : enum err echo_val_is_fresh(struct byte_array *cache_val,
118 : : struct byte_array *decrypted_payload)
119 : : {
120 : 5 : uint8_t code = 0;
121 : : struct byte_array unprotected_o_coap_payload;
122 : :
123 : : struct o_coap_option E_options[10];
124 : 5 : uint8_t E_options_cnt = 0;
125 : :
126 : : /* Parse decrypted payload: code + options + unprotected CoAP payload*/
127 [ - + ]: 5 : TRY(oscore_decrypted_payload_parser(decrypted_payload, &code, E_options,
128 : : &E_options_cnt,
129 : : &unprotected_o_coap_payload));
130 : :
131 [ + + ]: 7 : for (uint8_t i = 0; i < E_options_cnt; i++) {
132 [ + + ]: 5 : if (E_options[i].option_number == ECHO) {
133 [ + - ]: 3 : if (cache_val->len == E_options[i].len &&
134 [ + + ]: 3 : 0 == memcmp(E_options[i].value, cache_val->ptr, cache_val->len) ) {
135 : 1 : PRINT_MSG("ECHO option check -- OK\n");
136 : 1 : return ok;
137 : : } else {
138 : 2 : return echo_val_mismatch;
139 : : }
140 : : }
141 : : }
142 : :
143 : 2 : return no_echo_option;
144 : : }
145 : :
146 : :
147 : 28 : enum err uri_path_create(struct o_coap_option *options, uint32_t options_size,
148 : : uint8_t *uri_path, uint32_t *uri_path_size)
149 : : {
150 [ + - + - : 28 : if ((NULL == options) || (NULL == uri_path) ||
- + ]
151 : : (NULL == uri_path_size)) {
152 : 0 : return wrong_parameter;
153 : : }
154 : :
155 : 28 : uint32_t current_size = 0;
156 : 28 : uint32_t max_size = *uri_path_size;
157 : 28 : memset(uri_path, 0, max_size);
158 : :
159 : 28 : const uint8_t delimiter = '/';
160 : 28 : const uint32_t delimiter_size = 1;
161 : :
162 [ + + ]: 60 : for (uint32_t index = 0; index < options_size; index++) {
163 : 32 : struct o_coap_option *option = &options[index];
164 [ + + ]: 32 : if (URI_PATH != option->option_number) {
165 : 18 : continue;
166 : : }
167 [ + - - + ]: 14 : if ((0 != option->len) && (NULL == option->value)) {
168 : 0 : return oscore_wrong_uri_path;
169 : : }
170 : :
171 [ - + ]: 14 : TRY(buffer_append(uri_path, ¤t_size, max_size,
172 : : option->value, option->len));
173 [ - + ]: 14 : TRY(buffer_append(uri_path, ¤t_size, max_size, &delimiter,
174 : : delimiter_size));
175 : : }
176 : :
177 : : /* Remove last '/' character, or add a single one if the path is empty */
178 [ + + ]: 28 : if (current_size > 0) {
179 : 14 : uri_path[current_size] = 0;
180 : 14 : current_size--;
181 : : } else {
182 : 14 : uri_path[0] = delimiter;
183 : 14 : current_size = delimiter_size;
184 : : }
185 : :
186 : 28 : *uri_path_size = current_size;
187 : 28 : return ok;
188 : : }
|