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