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 : 33 : bool is_class_e(uint16_t code)
44 : : {
45 : : // blacklist, because OSCORE dictates that unknown options SHALL be processed as class E
46 [ + + + + : 29 : return code != URI_HOST && code != URI_PORT && code != OSCORE &&
+ + ]
47 [ + + + + ]: 62 : code != PROXY_URI && code != PROXY_SCHEME;
48 : : }
49 : :
50 : 24 : bool is_observe(struct o_coap_option *options, uint8_t options_cnt)
51 : : {
52 [ + + ]: 32 : for (uint8_t i = 0; i < options_cnt; i++) {
53 [ + + ]: 14 : if (options[i].option_number == OBSERVE) {
54 : 6 : return true;
55 : : }
56 : : }
57 : 18 : return false;
58 : : }
59 : :
60 : 41 : bool get_observe_value(struct o_coap_option *options, uint8_t options_cnt,
61 : : struct byte_array *output)
62 : : {
63 [ + - - + ]: 41 : if ((NULL == options) || (NULL == output)) {
64 : 0 : return false;
65 : : }
66 : :
67 [ + + ]: 79 : for (uint8_t i = 0; i < options_cnt; i++) {
68 [ + + ]: 44 : if (OBSERVE != options[i].option_number) {
69 : 38 : continue;
70 : : }
71 : :
72 : 6 : output->ptr = options[i].value;
73 : 6 : output->len = options[i].len;
74 : 6 : return true;
75 : : }
76 : 35 : output = NULL;
77 : 35 : return false;
78 : : }
79 : :
80 : 6 : enum err cache_echo_val(struct byte_array *dest, struct o_coap_option *options,
81 : : uint8_t options_cnt)
82 : : {
83 [ + + ]: 12 : for (uint8_t i = 0; i < options_cnt; i++) {
84 [ + + ]: 10 : if (options[i].option_number == ECHO) {
85 : 4 : PRINT_MSG("Caching the ECHO value!\n");
86 [ - + ]: 4 : TRY(_memcpy_s(dest->ptr, dest->len, options[i].value,
87 : : options[i].len));
88 : 4 : dest->len = options[i].len;
89 : 4 : return ok;
90 : : }
91 : : }
92 : 2 : return no_echo_option;
93 : : }
94 : :
95 : 18 : enum err oscore_decrypted_payload_parser(struct byte_array *in_payload,
96 : : uint8_t *out_code,
97 : : struct o_coap_option *out_E_options,
98 : : uint8_t *E_options_cnt,
99 : : struct byte_array *out_o_coap_payload)
100 : : {
101 : 18 : uint8_t *temp_payload_ptr = in_payload->ptr;
102 : 18 : uint32_t temp_payload_len = in_payload->len;
103 : :
104 : : /* Code */
105 : 18 : *out_code = *(temp_payload_ptr++);
106 : 18 : temp_payload_len--;
107 : :
108 : 18 : struct byte_array remaining_bytes =
109 : : BYTE_ARRAY_INIT(temp_payload_ptr, temp_payload_len);
110 [ - + ]: 18 : TRY(options_deserialize(&remaining_bytes, out_E_options, E_options_cnt,
111 : : out_o_coap_payload));
112 : :
113 : 18 : return ok;
114 : : }
115 : :
116 : 5 : enum err echo_val_is_fresh(struct byte_array *cache_val,
117 : : struct byte_array *decrypted_payload)
118 : : {
119 : 5 : uint8_t code = 0;
120 : : struct byte_array unprotected_o_coap_payload;
121 : :
122 : : struct o_coap_option E_options[10];
123 : 5 : uint8_t E_options_cnt = 0;
124 : :
125 : : /* Parse decrypted payload: code + options + unprotected CoAP payload*/
126 [ - + ]: 5 : TRY(oscore_decrypted_payload_parser(decrypted_payload, &code, E_options,
127 : : &E_options_cnt,
128 : : &unprotected_o_coap_payload));
129 : :
130 [ + + ]: 7 : for (uint8_t i = 0; i < E_options_cnt; i++) {
131 [ + + ]: 5 : if (E_options[i].option_number == ECHO) {
132 [ + - ]: 3 : if (cache_val->len == E_options[i].len &&
133 [ + + ]: 3 : 0 == memcmp(E_options[i].value, cache_val->ptr, cache_val->len) ) {
134 : 1 : PRINT_MSG("ECHO option check -- OK\n");
135 : 1 : return ok;
136 : : } else {
137 : 2 : return echo_val_mismatch;
138 : : }
139 : : }
140 : : }
141 : :
142 : 2 : return no_echo_option;
143 : : }
144 : :
145 : :
146 : 28 : enum err uri_path_create(struct o_coap_option *options, uint32_t options_size,
147 : : uint8_t *uri_path, uint32_t *uri_path_size)
148 : : {
149 [ + - + - : 28 : if ((NULL == options) || (NULL == uri_path) ||
- + ]
150 : : (NULL == uri_path_size)) {
151 : 0 : return wrong_parameter;
152 : : }
153 : :
154 : 28 : uint32_t current_size = 0;
155 : 28 : uint32_t max_size = *uri_path_size;
156 : 28 : memset(uri_path, 0, max_size);
157 : :
158 : 28 : const uint8_t delimiter = '/';
159 : 28 : const uint32_t delimiter_size = 1;
160 : :
161 [ + + ]: 60 : for (uint32_t index = 0; index < options_size; index++) {
162 : 32 : struct o_coap_option *option = &options[index];
163 [ + + ]: 32 : if (URI_PATH != option->option_number) {
164 : 18 : continue;
165 : : }
166 [ + - - + ]: 14 : if ((0 != option->len) && (NULL == option->value)) {
167 : 0 : return oscore_wrong_uri_path;
168 : : }
169 : :
170 [ - + ]: 14 : TRY(buffer_append(uri_path, ¤t_size, max_size,
171 : : option->value, option->len));
172 [ - + ]: 14 : TRY(buffer_append(uri_path, ¤t_size, max_size, &delimiter,
173 : : delimiter_size));
174 : : }
175 : :
176 : : /* Remove last '/' character, or add a single one if the path is empty */
177 [ + + ]: 28 : if (current_size > 0) {
178 : 14 : uri_path[current_size] = 0;
179 : 14 : current_size--;
180 : : } else {
181 : 14 : uri_path[0] = delimiter;
182 : 14 : current_size = delimiter_size;
183 : : }
184 : :
185 : 28 : *uri_path_size = current_size;
186 : 28 : return ok;
187 : : }
|