1 /*
2 * Copyright (c) 2021 - 2023, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 #include "nrf_802154_security_pib.h"
36
37 #include "nrf_802154_config.h"
38 #include "nrf_802154_const.h"
39 #include "nrf_802154_sl_atomics.h"
40
41 #include <string.h>
42 #include <stdbool.h>
43 #include <assert.h>
44
45 typedef struct
46 {
47 uint8_t key[AES_CCM_KEY_SIZE];
48 uint8_t id[KEY_ID_MODE_3_SIZE];
49 nrf_802154_key_id_mode_t mode;
50 uint32_t frame_counter;
51 bool use_global_frame_counter;
52 bool taken;
53 } table_entry_t;
54
55 static table_entry_t m_key_storage[NRF_802154_SECURITY_KEY_STORAGE_SIZE];
56 static uint32_t m_global_frame_counter;
57
mode_is_valid(nrf_802154_key_id_mode_t mode)58 static bool mode_is_valid(nrf_802154_key_id_mode_t mode)
59 {
60 switch (mode)
61 {
62 case KEY_ID_MODE_0:
63 case KEY_ID_MODE_1:
64 case KEY_ID_MODE_2:
65 case KEY_ID_MODE_3:
66 return true;
67
68 default:
69 return false;
70 }
71 }
72
id_length_get(nrf_802154_key_id_mode_t mode)73 static int id_length_get(nrf_802154_key_id_mode_t mode)
74 {
75 switch (mode)
76 {
77 case 1:
78 return KEY_ID_MODE_1_SIZE;
79
80 case 2:
81 return KEY_ID_MODE_2_SIZE;
82
83 case 3:
84 return KEY_ID_MODE_3_SIZE;
85
86 default:
87 return 0;
88 }
89 }
90
key_matches(table_entry_t * p_key,nrf_802154_key_id_t * p_id)91 static bool key_matches(table_entry_t * p_key, nrf_802154_key_id_t * p_id)
92 {
93 if (!p_key->taken)
94 {
95 return false;
96 }
97
98 if (p_key->mode != p_id->mode)
99 {
100 return false;
101 }
102
103 if (p_id->mode == KEY_ID_MODE_0)
104 {
105 return true;
106 }
107 else if ((p_id->p_key_id == NULL) ||
108 (memcmp(p_id->p_key_id, p_key->id, id_length_get(p_id->mode)) != 0))
109 {
110 return false;
111 }
112 else
113 {
114 return true;
115 }
116 }
117
key_is_present(nrf_802154_key_id_t * p_id)118 static bool key_is_present(nrf_802154_key_id_t * p_id)
119 {
120 for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
121 {
122 if (key_matches(&m_key_storage[i], p_id))
123 {
124 return true;
125 }
126 }
127
128 return false;
129 }
130
nrf_802154_security_pib_init(void)131 nrf_802154_security_error_t nrf_802154_security_pib_init(void)
132 {
133 for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
134 {
135 m_key_storage[i].taken = false;
136 }
137
138 return NRF_802154_SECURITY_ERROR_NONE;
139 }
140
nrf_802154_security_pib_deinit(void)141 nrf_802154_security_error_t nrf_802154_security_pib_deinit(void)
142 {
143 return NRF_802154_SECURITY_ERROR_NONE;
144 }
145
nrf_802154_security_pib_key_store(nrf_802154_key_t * p_key)146 nrf_802154_security_error_t nrf_802154_security_pib_key_store(nrf_802154_key_t * p_key)
147 {
148 assert(p_key != NULL);
149
150 if (p_key->type != NRF_802154_KEY_CLEARTEXT)
151 {
152 return NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED;
153 }
154
155 if (!mode_is_valid(p_key->id.mode))
156 {
157 return NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED;
158 }
159
160 if (key_is_present(&p_key->id))
161 {
162 return NRF_802154_SECURITY_ERROR_ALREADY_PRESENT;
163 }
164
165 for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
166 {
167 if (m_key_storage[i].taken == false)
168 {
169 memcpy(m_key_storage[i].key,
170 p_key->value.p_cleartext_key,
171 sizeof(m_key_storage[i].key));
172 m_key_storage[i].mode = p_key->id.mode;
173 memcpy(m_key_storage[i].id, p_key->id.p_key_id, id_length_get(p_key->id.mode));
174 m_key_storage[i].frame_counter = p_key->frame_counter;
175 m_key_storage[i].use_global_frame_counter = p_key->use_global_frame_counter;
176
177 __DMB();
178
179 m_key_storage[i].taken = true;
180 return NRF_802154_SECURITY_ERROR_NONE;
181 }
182 }
183
184 return NRF_802154_SECURITY_ERROR_STORAGE_FULL;
185 }
186
nrf_802154_security_pib_key_remove(nrf_802154_key_id_t * p_id)187 nrf_802154_security_error_t nrf_802154_security_pib_key_remove(nrf_802154_key_id_t * p_id)
188 {
189 assert(p_id != NULL);
190
191 for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
192 {
193 if (key_matches(&m_key_storage[i], p_id))
194 {
195 m_key_storage[i].taken = false;
196 return NRF_802154_SECURITY_ERROR_NONE;
197 }
198 }
199
200 return NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND;
201 }
202
nrf_802154_security_pib_key_use(nrf_802154_key_id_t * p_id,void * destination)203 nrf_802154_security_error_t nrf_802154_security_pib_key_use(nrf_802154_key_id_t * p_id,
204 void * destination)
205 {
206 assert(destination != NULL);
207 assert(p_id != NULL);
208
209 for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
210 {
211 if (key_matches(&m_key_storage[i], p_id))
212 {
213 memcpy((uint8_t *)destination, m_key_storage[i].key, sizeof(m_key_storage[i].key));
214 return NRF_802154_SECURITY_ERROR_NONE;
215 }
216 }
217
218 return NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND;
219 }
220
nrf_802154_security_pib_global_frame_counter_set(uint32_t frame_counter)221 void nrf_802154_security_pib_global_frame_counter_set(uint32_t frame_counter)
222 {
223 m_global_frame_counter = frame_counter;
224 }
225
nrf_802154_security_pib_global_frame_counter_set_if_larger(uint32_t frame_counter)226 void nrf_802154_security_pib_global_frame_counter_set_if_larger(uint32_t frame_counter)
227 {
228 uint32_t fc;
229
230 do
231 {
232 fc = m_global_frame_counter;
233
234 if (fc >= frame_counter)
235 {
236 break;
237 }
238
239 }
240 while (!nrf_802154_sl_atomic_cas_u32(&m_global_frame_counter, &fc, frame_counter));
241 }
242
nrf_802154_security_pib_frame_counter_get_next(uint32_t * p_frame_counter,nrf_802154_key_id_t * p_id)243 nrf_802154_security_error_t nrf_802154_security_pib_frame_counter_get_next(
244 uint32_t * p_frame_counter,
245 nrf_802154_key_id_t * p_id)
246 {
247 assert(p_frame_counter != NULL);
248 assert(p_id != NULL);
249
250 uint32_t * p_frame_counter_to_use = NULL;
251 uint32_t fc;
252
253 for (uint32_t i = 0; i < NRF_802154_SECURITY_KEY_STORAGE_SIZE; i++)
254 {
255 if (key_matches(&m_key_storage[i], p_id))
256 {
257 if (m_key_storage[i].use_global_frame_counter)
258 {
259 p_frame_counter_to_use = &m_global_frame_counter;
260 }
261 else
262 {
263 p_frame_counter_to_use = &m_key_storage[i].frame_counter;
264 }
265 break;
266 }
267 }
268
269 if (p_frame_counter_to_use == NULL)
270 {
271 /* No proper key found. */
272 return NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND;
273 }
274
275 do
276 {
277 fc = __LDREXW(p_frame_counter_to_use);
278
279 if (fc == UINT32_MAX)
280 {
281 __CLREX();
282 return NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW;
283 }
284 }
285 while (__STREXW(fc + 1, p_frame_counter_to_use));
286
287 *p_frame_counter = *p_frame_counter_to_use - 1;
288
289 return NRF_802154_SECURITY_ERROR_NONE;
290 }
291