Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rf4ce-secur.c
Line
Count
Source
1
/* packet-rf4ce-secur.c
2
 * Security related functions and objects for RF4CE dissector
3
 * Copyright (C) Atmosic 2023
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "packet-rf4ce-secur.h"
13
#include "packet-zbee-security.h"
14
#include "packet-ieee802154.h"
15
#include <wsutil/wsgcrypt.h>
16
#include <epan/proto_data.h>
17
18
#ifdef RF4CE_DEBUG_EN
19
void rf4ce_print_arr(const char *str, uint8_t *ptr, uint16_t len);
20
#define RF4CE_PRINT_ARR(s, p, l) rf4ce_print_arr(s, p, l)
21
#else
22
#define RF4CE_PRINT_ARR(s, p, l)
23
#endif /* RF4CE_DEBUG_EN */
24
25
static keypair_context_t keypair_context;
26
static key_exchange_context_t key_exchange_context;
27
static addr_entry_t addr_table[RF4CE_ADDR_TABLE_SIZE];
28
static nwk_key_entry_t nwk_key_storage[RF4CE_NWK_KEY_STORAGE_SIZE];
29
static vendor_secret_entry_t vendor_secret_storage[RF4CE_VENDOR_SECRET_STORAGE_SIZE];
30
31
static void keypair_context_calc_key(uint8_t *nwk_key);
32
static nwk_key_entry_t *nwk_key_storage_get_entry_by_key(uint8_t *nwk_key, bool key_from_gui);
33
34
static void reverse(uint8_t *dest, uint8_t *src, uint16_t size);
35
36
/* RF4CE GDP 2.0 spec, part 7.4.1 Key Exchange negotiation
37
 * Default secret: This is a 128bit "secret" that is known to all devices that are certified to
38
 * conform to this specification. The value shall be set to the following octet string (lowest order
39
 * octet first)
40
 * Note that this value should be expected to be widely known and the overall link security
41
 * should not depend on this value remaining a secret.
42
 */
43
uint8_t DEFAULT_SECRET[SEC_STR_LEN] =
44
    {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
45
     0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
46
47
void keypair_context_init(const uint8_t *controller_ieee, const uint8_t *target_ieee, uint8_t expected_transfer_count)
48
4
{
49
4
    if ((controller_ieee == NULL) || (target_ieee == NULL))
50
3
    {
51
3
        return;
52
3
    }
53
1
    memset(&keypair_context, 0, sizeof(keypair_context_t));
54
55
1
    memcpy(keypair_context.controller_addr, controller_ieee, RF4CE_IEEE_ADDR_LEN);
56
1
    memcpy(keypair_context.target_addr, target_ieee, RF4CE_IEEE_ADDR_LEN);
57
58
1
    keypair_context.nwk_key_exchange_transfer_expected = expected_transfer_count;
59
1
}
60
61
static void keypair_context_calc_key(uint8_t *nwk_key)
62
0
{
63
0
    for (int i = 0; i < keypair_context.nwk_key_exchange_transfer_received; i++)
64
0
    {
65
0
        for (int j = 0; j < KEY_LEN; j++)
66
0
        {
67
0
            keypair_context.nwk_key_seed[(i + 1) * KEY_LEN + j] ^= keypair_context.nwk_key_seed[i * KEY_LEN + j];
68
0
        }
69
0
    }
70
71
0
    memcpy(nwk_key, &keypair_context.nwk_key_seed[RF4CE_NWK_KEY_SEED_DATA_LENGTH - KEY_LEN], KEY_LEN);
72
0
}
73
74
void keypair_context_update_seed(uint8_t *seed, uint8_t seed_seqn)
75
0
{
76
0
    bool is_retransmit = (seed_seqn == keypair_context.nwk_key_exchange_transfer_received - 1);
77
0
    bool is_latest_seed = (seed_seqn + 1 == keypair_context.nwk_key_exchange_transfer_expected);
78
79
    /* retransmitt of the latest key seed - we must to re-calculate a NWK key */
80
0
    if (is_retransmit && is_latest_seed)
81
0
    {
82
0
        memcpy(keypair_context.nwk_key_seed, keypair_context.nwk_key_seed_prev, RF4CE_NWK_KEY_SEED_DATA_LENGTH);
83
0
    }
84
85
0
    if (seed_seqn == 0)
86
0
    {
87
0
        memcpy(keypair_context.nwk_key_seed_latest, seed, RF4CE_NWK_KEY_SEED_DATA_LENGTH);
88
0
        keypair_context.nwk_key_exchange_transfer_received = 1;
89
0
        return;
90
0
    }
91
92
    /* Retransmit of the previous key seed. Should take this one */
93
0
    if (is_retransmit)
94
0
    {
95
        /* save this one as a candidate */
96
0
        memcpy(keypair_context.nwk_key_seed_latest, seed, RF4CE_NWK_KEY_SEED_DATA_LENGTH);
97
98
        /* move on if it's the latest seed to re-calculate a NWK key */
99
0
        if (!is_latest_seed)
100
0
        {
101
0
            return;
102
0
        }
103
0
    }
104
105
0
    if (seed_seqn == keypair_context.nwk_key_exchange_transfer_received)
106
0
    {
107
        /* Apply previous key seed, it has been accepted since we received the next one */
108
0
        for (int i = 0; i < RF4CE_NWK_KEY_SEED_DATA_LENGTH; i++)
109
0
        {
110
0
            keypair_context.nwk_key_seed[i] ^= keypair_context.nwk_key_seed_latest[i];
111
0
        }
112
113
        /* save this one as a candidate */
114
0
        memcpy(keypair_context.nwk_key_seed_latest, seed, RF4CE_NWK_KEY_SEED_DATA_LENGTH);
115
0
        keypair_context.nwk_key_exchange_transfer_received += 1;
116
0
    }
117
118
0
    if (is_latest_seed)
119
0
    {
120
0
        uint8_t nwk_key[KEY_LEN] = {0};
121
0
        addr_entry_t *controller_addr_ent = rf4ce_addr_table_get_addr_entry_by_ieee(keypair_context.controller_addr);
122
0
        addr_entry_t *target_addr_ent = rf4ce_addr_table_get_addr_entry_by_ieee(keypair_context.target_addr);
123
124
        /* save the current key seed to avoid retransmitts of the latest one in future */
125
0
        memcpy(keypair_context.nwk_key_seed_prev, keypair_context.nwk_key_seed, RF4CE_NWK_KEY_SEED_DATA_LENGTH);
126
127
0
        for (int i = 0; i < RF4CE_NWK_KEY_SEED_DATA_LENGTH; i++)
128
0
        {
129
0
            keypair_context.nwk_key_seed[i] ^= keypair_context.nwk_key_seed_latest[i];
130
0
        }
131
132
0
        keypair_context_calc_key(nwk_key);
133
134
0
        nwk_key_storage_add_entry(
135
0
            nwk_key,
136
0
            controller_addr_ent,
137
0
            target_addr_ent,
138
0
            false, /* key from commissioning session */
139
0
            true); /* is_pairing_key                 */
140
0
    }
141
0
}
142
143
static nwk_key_entry_t *nwk_key_storage_get_entry_by_key(uint8_t *nwk_key, bool key_from_gui)
144
0
{
145
0
    nwk_key_entry_t *entry = NULL;
146
0
    int idx = 0;
147
148
0
    while (idx < RF4CE_NWK_KEY_STORAGE_SIZE)
149
0
    {
150
0
        if (nwk_key_storage[idx].is_used && (nwk_key_storage[idx].key_from_gui == key_from_gui) && (memcmp(nwk_key_storage[idx].nwk_key, nwk_key, KEY_LEN) == 0))
151
0
        {
152
0
            entry = nwk_key_storage + idx;
153
0
            break;
154
0
        }
155
156
0
        idx++;
157
0
    }
158
159
0
    return entry;
160
0
}
161
162
void nwk_key_storage_add_entry(uint8_t *nwk_key, addr_entry_t *controller_addr_ent, addr_entry_t *target_addr_ent, bool key_from_gui, bool is_pairing_key)
163
0
{
164
    /* find an existing entry so as not to add duplicates */
165
0
    nwk_key_entry_t *nwk_key_entry = nwk_key_storage_get_entry_by_key(nwk_key, key_from_gui);
166
167
0
    if (nwk_key_entry == NULL)
168
0
    {
169
0
        int idx = 0;
170
171
0
        while (idx < RF4CE_NWK_KEY_STORAGE_SIZE)
172
0
        {
173
0
            if (!nwk_key_storage[idx].is_used)
174
0
            {
175
0
                memcpy(nwk_key_storage[idx].nwk_key, nwk_key, KEY_LEN);
176
0
                nwk_key_storage[idx].controller_addr_ent = controller_addr_ent;
177
0
                nwk_key_storage[idx].target_addr_ent = target_addr_ent;
178
0
                nwk_key_storage[idx].key_from_gui = key_from_gui;
179
0
                nwk_key_storage[idx].is_used = true;
180
0
                nwk_key_storage[idx].is_pairing_key = is_pairing_key;
181
0
                break;
182
0
            }
183
184
0
            idx++;
185
0
        }
186
0
    }
187
0
}
188
189
void nwk_key_storage_release_entry(uint8_t *nwk_key, bool key_from_gui)
190
0
{
191
0
    nwk_key_entry_t *nwk_key_entry = nwk_key_storage_get_entry_by_key(nwk_key, key_from_gui);
192
193
0
    if (nwk_key_entry != NULL)
194
0
    {
195
0
        nwk_key_entry->is_used = false;
196
0
    }
197
0
}
198
199
void rf4ce_addr_table_add_addrs(const void *ieee_addr, uint16_t short_addr)
200
16
{
201
16
    unsigned idx = 0;
202
203
16
    if (ieee_addr == NULL)
204
2
    {
205
2
        return;
206
2
    }
207
208
    /* search for addresses so as not to add duplicates */
209
1.44k
    while (idx < RF4CE_ADDR_TABLE_SIZE)
210
1.43k
    {
211
1.43k
        if (addr_table[idx].is_used && (memcmp(addr_table[idx].ieee_addr, ieee_addr, RF4CE_IEEE_ADDR_LEN) == 0) && addr_table[idx].short_addr == short_addr)
212
3
        {
213
3
            return;
214
3
        }
215
216
1.42k
        idx++;
217
1.42k
    }
218
219
    /* no duplicates found, search for a free slot */
220
11
    idx = 0;
221
66
    while (idx < RF4CE_ADDR_TABLE_SIZE && addr_table[idx].is_used)
222
55
    {
223
55
        idx++;
224
55
    }
225
226
11
    if (idx < RF4CE_ADDR_TABLE_SIZE)
227
11
    {
228
11
        memcpy(addr_table[idx].ieee_addr, ieee_addr, RF4CE_IEEE_ADDR_LEN);
229
11
        addr_table[idx].short_addr = short_addr;
230
11
        addr_table[idx].is_used = true;
231
11
    }
232
11
}
233
234
bool rf4ce_addr_table_get_ieee_addr(uint8_t *ieee_addr, packet_info *pinfo, bool is_src)
235
152
{
236
152
    bool addr_found = false;
237
152
    address_type addr_type;
238
152
    ieee802154_hints_t *hints;
239
152
    const void *p_addr = NULL;
240
152
    uint16_t short_addr = 0xffff;
241
242
    /* Check inputs */
243
152
    if ((ieee_addr == NULL) || (pinfo == NULL))
244
0
    {
245
0
        return false;
246
0
    }
247
152
    if (is_src)
248
76
    {
249
76
        addr_type = pinfo->dl_src.type;
250
76
        p_addr = pinfo->dl_src.data;
251
76
    }
252
76
    else
253
76
    {
254
76
        addr_type = pinfo->dl_dst.type;
255
76
        p_addr = pinfo->dl_dst.data;
256
76
    }
257
152
    if (addr_type == AT_EUI64)
258
29
    {
259
29
        if (p_addr == NULL)
260
0
        {
261
0
            return false;
262
0
        }
263
29
    }
264
123
    else
265
123
    {
266
        /* Get addresses */
267
123
        hints = (ieee802154_hints_t *)p_get_proto_data(wmem_file_scope(),
268
123
                                                       pinfo,
269
123
                                                       proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN),
270
123
                                                       0
271
123
        );
272
123
        if (hints == NULL)
273
0
        {
274
0
            return false;
275
0
        }
276
123
        short_addr = (is_src) ? hints->src16 : hints->dst16;
277
123
    }
278
    /* Search address in address table */
279
19.4k
    for (unsigned idx = 0; idx < RF4CE_ADDR_TABLE_SIZE; idx++)
280
19.3k
    {
281
19.3k
        if (addr_table[idx].is_used)
282
572
        {
283
572
            if (addr_type == AT_EUI64)
284
81
            {
285
81
                if (memcmp(addr_table[idx].ieee_addr, p_addr, RF4CE_IEEE_ADDR_LEN) == 0) {
286
1
                    addr_found = true;
287
1
                }
288
81
            }
289
491
            else
290
491
            {
291
491
                if (addr_table[idx].short_addr == short_addr) {
292
0
                    addr_found = true;
293
0
                }
294
491
            }
295
572
            if (addr_found)
296
1
            {
297
1
                memcpy(ieee_addr, addr_table[idx].ieee_addr, RF4CE_IEEE_ADDR_LEN);
298
1
                break;
299
1
            }
300
572
        }
301
19.3k
    }
302
152
    return addr_found;
303
152
}
304
305
addr_entry_t *rf4ce_addr_table_get_addr_entry_by_ieee(uint8_t *ieee_addr)
306
0
{
307
0
    addr_entry_t *entry = NULL;
308
0
    unsigned idx = 0;
309
310
0
    while (ieee_addr != NULL && idx < RF4CE_ADDR_TABLE_SIZE)
311
0
    {
312
0
        if (addr_table[idx].is_used && memcmp(addr_table[idx].ieee_addr, ieee_addr, RF4CE_IEEE_ADDR_LEN) == 0)
313
0
        {
314
0
            entry = addr_table + idx;
315
0
            break;
316
0
        }
317
318
0
        idx++;
319
0
    }
320
321
0
    return entry;
322
0
}
323
324
void key_exchange_context_init(void)
325
0
{
326
0
    memset(&key_exchange_context.rand_a, 0, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH);
327
0
    memset(&key_exchange_context.rand_b, 0, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH);
328
0
    memset(&key_exchange_context.mac_a, 0, RF4CE_IEEE_ADDR_LEN);
329
0
    memset(&key_exchange_context.mac_b, 0, RF4CE_IEEE_ADDR_LEN);
330
0
}
331
332
void key_exchange_context_start_procedure(void)
333
0
{
334
0
    if (!key_exchange_context.is_proc_started)
335
0
    {
336
0
        key_exchange_context.is_proc_started = true;
337
0
    }
338
0
}
339
340
void key_exchange_context_stop_procedure(void)
341
0
{
342
0
    if (key_exchange_context.is_proc_started)
343
0
    {
344
0
        key_exchange_context.is_proc_started = false;
345
0
    }
346
0
}
347
348
bool key_exchange_context_is_procedure_started(void)
349
0
{
350
0
    return key_exchange_context.is_proc_started;
351
0
}
352
353
void key_exchange_context_set_rand_a(uint8_t *rand_a)
354
0
{
355
0
    if (rand_a != NULL)
356
0
    {
357
0
        memcpy(key_exchange_context.rand_a, rand_a, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH);
358
0
    }
359
0
}
360
361
void key_exchange_context_set_rand_b(uint8_t *rand_b)
362
0
{
363
0
    if (rand_b != NULL)
364
0
    {
365
0
        memcpy(key_exchange_context.rand_b, rand_b, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH);
366
0
    }
367
0
}
368
369
void key_exchange_context_set_mac_a(uint8_t *mac_a)
370
0
{
371
0
    if (mac_a != NULL)
372
0
    {
373
0
        memcpy(key_exchange_context.mac_a, mac_a, RF4CE_IEEE_ADDR_LEN);
374
0
    }
375
0
}
376
377
void key_exchange_context_set_mac_b(uint8_t *mac_b)
378
0
{
379
0
    if (mac_b != NULL)
380
0
    {
381
0
        memcpy(key_exchange_context.mac_b, mac_b, RF4CE_IEEE_ADDR_LEN);
382
0
    }
383
0
}
384
385
#ifdef RF4CE_DEBUG_EN
386
void rf4ce_print_arr(const char *str, uint8_t *ptr, uint16_t len)
387
{
388
  g_print("%s: ", str);
389
  for (uint16_t i = 0; i < len-1; i++)
390
  {
391
    g_print("%02x:", *(ptr+i));
392
  }
393
  g_print("%02x\n", *(ptr+len-1));
394
}
395
#endif /* RF4CE_DEBUG_EN */
396
397
static bool calc_key_cmac(uint8_t *secret, uint8_t *nwk_key, uint32_t tag_b_pack, uint8_t *key_out)
398
0
{
399
0
    uint8_t mac_a[RF4CE_IEEE_ADDR_LEN];
400
0
    uint8_t mac_b[RF4CE_IEEE_ADDR_LEN];
401
402
0
    uint8_t *rand_a = key_exchange_context.rand_a;
403
0
    uint8_t *rand_b = key_exchange_context.rand_b;
404
405
0
    uint8_t k_dk_data[RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH +
406
0
                      RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH];
407
0
    uint8_t k_dk_data_reversed[RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH +
408
0
                               RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH];
409
410
0
    uint8_t context_data[CONTEXT_STR_LEN + RF4CE_IEEE_ADDR_LEN +
411
0
                         RF4CE_IEEE_ADDR_LEN + KEY_LEN];
412
413
0
    uint8_t k_dk_key[KEY_LEN];
414
0
    uint8_t new_key[KEY_LEN];
415
416
0
    uint8_t dummy[KEY_LEN];
417
0
    uint32_t tag_b_calc;
418
419
0
    uint8_t *data_ptr;
420
421
0
    reverse(mac_a, key_exchange_context.mac_a, RF4CE_IEEE_ADDR_LEN);
422
0
    reverse(mac_b, key_exchange_context.mac_b, RF4CE_IEEE_ADDR_LEN);
423
424
0
    data_ptr = k_dk_data;
425
0
    memcpy(data_ptr, rand_a, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH);
426
0
    data_ptr += RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH;
427
0
    memcpy(data_ptr, rand_b, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH);
428
429
0
    data_ptr = k_dk_data_reversed;
430
0
    memcpy(data_ptr, rand_b, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH);
431
0
    data_ptr += RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_B_LENGTH;
432
0
    memcpy(data_ptr, rand_a, RF4CE_PROFILE_CMD_KEY_EXCHANGE_RAND_A_LENGTH);
433
434
0
    data_ptr = context_data;
435
0
    memcpy(data_ptr, CONTEXT_STR, CONTEXT_STR_LEN);
436
0
    data_ptr += CONTEXT_STR_LEN;
437
0
    memcpy(data_ptr, mac_a, RF4CE_IEEE_ADDR_LEN);
438
0
    data_ptr += RF4CE_IEEE_ADDR_LEN;
439
0
    memcpy(data_ptr, mac_b, RF4CE_IEEE_ADDR_LEN);
440
0
    data_ptr += RF4CE_IEEE_ADDR_LEN;
441
0
    memcpy(data_ptr, nwk_key, KEY_LEN);
442
443
    /* Generic Device Profile Version 2.0
444
     * 7.4.2 Key generation
445
     * Calculate derivation key
446
     * K_dk = AES-128-CMAC (RAND-A || RAND-B, Shared secret)
447
     */
448
0
    rf4ce_aes_cmac(secret, SEC_STR_LEN, k_dk_data, k_dk_key);
449
450
    /* Calculate new link key
451
     * Link key = AES-128-CMAC (K_dk, context || label || pairing key)
452
     */
453
0
    rf4ce_aes_cmac(context_data, sizeof(context_data), k_dk_key, new_key);
454
455
    /* Calculate TAG-B value
456
     * TAG-B = AES-128-CMAC(link key, RAND-B || RAND-A)
457
     */
458
0
    rf4ce_aes_cmac(k_dk_data_reversed, sizeof(k_dk_data_reversed), new_key, dummy);
459
0
    memcpy((uint8_t *)&tag_b_calc, dummy, RF4CE_PROFILE_CMD_KEY_EXCHANGE_TAG_A_LENGTH);
460
461
0
    RF4CE_PRINT_ARR("tag_b_calc", (uint8_t *)&tag_b_calc, 4);
462
0
    RF4CE_PRINT_ARR("   new_key", new_key, 16);
463
464
0
    if (tag_b_pack == tag_b_calc)
465
0
    {
466
0
        memcpy(key_out, new_key, KEY_LEN);
467
0
        return true;
468
0
    }
469
470
0
    return false;
471
0
}
472
473
static bool key_exchange_calc_key_cont(uint8_t *secret, uint32_t tag_b_pack, bool try_pairing_key, uint8_t *new_key_out)
474
0
{
475
0
    bool is_new_key_found = false;
476
477
0
    for (unsigned i = 0; i < RF4CE_NWK_KEY_STORAGE_SIZE; i++)
478
0
    {
479
0
        if (nwk_key_storage[i].is_used && ((try_pairing_key && nwk_key_storage[i].is_pairing_key) || (!try_pairing_key && nwk_key_storage[i].key_from_gui)))
480
0
        {
481
0
            is_new_key_found = calc_key_cmac(secret, nwk_key_storage[i].nwk_key, tag_b_pack, new_key_out);
482
483
0
            if (is_new_key_found)
484
0
            {
485
0
                break;
486
0
            }
487
0
        }
488
0
    }
489
490
0
    return is_new_key_found;
491
0
}
492
493
void key_exchange_calc_key(uint32_t tag_b_pack)
494
0
{
495
0
    uint8_t *controller_addr = key_exchange_context.mac_a;
496
0
    uint8_t *target_addr = key_exchange_context.mac_b;
497
498
0
    addr_entry_t *controller_addr_ent = rf4ce_addr_table_get_addr_entry_by_ieee(controller_addr);
499
0
    addr_entry_t *target_addr_ent = rf4ce_addr_table_get_addr_entry_by_ieee(target_addr);
500
501
0
    uint8_t *secret;
502
503
0
    uint8_t new_key[KEY_LEN];
504
0
    bool is_new_key_found = false;
505
506
0
    for (unsigned i = 0; i < RF4CE_VENDOR_SECRET_STORAGE_SIZE; i++)
507
0
    {
508
0
        if (!vendor_secret_storage[i].is_used)
509
0
        {
510
0
            continue;
511
0
        }
512
513
0
        secret = vendor_secret_storage[i].secret;
514
515
        /* try all the pairing keys first */
516
0
        is_new_key_found = key_exchange_calc_key_cont(secret, tag_b_pack, true, new_key);
517
518
        /* try other keys */
519
0
        if (!is_new_key_found)
520
0
        {
521
0
            is_new_key_found = key_exchange_calc_key_cont(secret, tag_b_pack, false, new_key);
522
0
        }
523
524
0
        if (is_new_key_found)
525
0
        {
526
0
            nwk_key_storage_add_entry(
527
0
                new_key,
528
0
                controller_addr_ent,
529
0
                target_addr_ent,
530
0
                false,  /* key from the Key Exchange procedure */
531
0
                false); /* !is_pairing_key */
532
533
0
            break;
534
0
        }
535
0
    }
536
0
}
537
538
static vendor_secret_entry_t *vendor_secret_storage_get_entry(uint8_t *secret)
539
15
{
540
15
    vendor_secret_entry_t *entry = NULL;
541
15
    int idx = 0;
542
543
975
    while (idx < RF4CE_VENDOR_SECRET_STORAGE_SIZE)
544
960
    {
545
960
        if (vendor_secret_storage[idx].is_used && (memcmp(vendor_secret_storage[idx].secret, secret, SEC_STR_LEN) == 0))
546
0
        {
547
0
            entry = vendor_secret_storage + idx;
548
0
            break;
549
0
        }
550
551
960
        idx++;
552
960
    }
553
554
15
    return entry;
555
15
}
556
557
void vendor_secret_storage_add_entry(uint8_t *secret)
558
15
{
559
15
    unsigned idx = 0;
560
15
    vendor_secret_entry_t *entry = vendor_secret_storage_get_entry(secret);
561
562
15
    if (entry != NULL)
563
0
    {
564
0
        return;
565
0
    }
566
567
15
    while (idx < RF4CE_VENDOR_SECRET_STORAGE_SIZE && vendor_secret_storage[idx].is_used)
568
0
    {
569
0
        idx++;
570
0
    }
571
572
15
    if (idx < RF4CE_VENDOR_SECRET_STORAGE_SIZE)
573
15
    {
574
15
        memcpy(vendor_secret_storage[idx].secret, secret, SEC_STR_LEN);
575
15
        vendor_secret_storage[idx].is_used = true;
576
15
    }
577
15
}
578
579
void vendor_secret_storage_release_entry(uint8_t *secret)
580
0
{
581
0
    vendor_secret_entry_t *entry = vendor_secret_storage_get_entry(secret);
582
583
0
    if (entry != NULL)
584
0
    {
585
0
        entry->is_used = false;
586
0
    }
587
0
}
588
589
void rf4ce_secur_cleanup(void)
590
0
{
591
0
    int idx = 0;
592
593
0
    memset(&keypair_context, 0, sizeof(keypair_context));
594
0
    memset(addr_table, 0, sizeof(addr_table));
595
596
0
    while (idx < RF4CE_NWK_KEY_STORAGE_SIZE)
597
0
    {
598
0
        if (nwk_key_storage[idx].is_used && !nwk_key_storage[idx].key_from_gui)
599
0
        {
600
0
            nwk_key_storage[idx].is_used = false;
601
0
        }
602
603
0
        idx++;
604
0
    }
605
0
}
606
607
static void reverse(uint8_t *dest, uint8_t *src, uint16_t size)
608
0
{
609
0
    for (int i = 0; i < size; i++)
610
0
    {
611
0
        dest[size - i - 1] = src[i];
612
0
    }
613
0
}
614
615
bool decrypt_data(
616
    const uint8_t *in, uint8_t *out,
617
    uint16_t payload_offset,
618
    uint16_t *len,
619
    uint8_t src_ieee[RF4CE_IEEE_ADDR_LEN], uint8_t dst_ieee[RF4CE_IEEE_ADDR_LEN])
620
4
{
621
4
    bool ret = false;
622
4
    uint8_t frame_control = *in;
623
4
    int idx = 0;
624
625
4
    if (*len < RF4CE_MIN_NWK_LENGTH || *len > RF4CE_MAX_NWK_LENGTH)
626
0
    {
627
0
        return false;
628
0
    }
629
630
4
    if (*len < payload_offset + RF4CE_CCM_M) {
631
1
        return false;
632
1
    }
633
634
195
    while (idx < RF4CE_NWK_KEY_STORAGE_SIZE)
635
192
    {
636
192
        if (nwk_key_storage[idx].is_used)
637
0
        {
638
0
            uint8_t *data_ptr;
639
640
            /* Form the nonce (3.5.11.3 Outgoing frame security) */
641
0
            uint8_t nonce[RF4CE_IEEE_ADDR_LEN + 4 + 1];
642
643
0
            data_ptr = nonce;
644
            /* Source IEEE address */
645
0
            reverse(data_ptr, src_ieee, RF4CE_IEEE_ADDR_LEN);
646
0
            data_ptr += RF4CE_IEEE_ADDR_LEN;
647
            /* Fetch frame counter from the packet (don't check) */
648
0
            memcpy(data_ptr, in + 1, 4);
649
0
            data_ptr += 4;
650
            /* Security level */
651
0
            *data_ptr = RF4CE_SECUR_CONTROL;
652
653
            /* Form the auth string (3.5.11.3 Outgoing frame security) */
654
0
            uint8_t auth[1 + 4 + RF4CE_IEEE_ADDR_LEN];
655
656
0
            data_ptr = auth;
657
            /* Frame control field */
658
0
            *data_ptr = frame_control;
659
0
            data_ptr += 1;
660
            /* Fetch frame counter from the packet (don't check) */
661
0
            memcpy(data_ptr, in + 1, 4);
662
0
            data_ptr += 4;
663
            /* Destination IEEE address */
664
0
            reverse(data_ptr, dst_ieee, RF4CE_IEEE_ADDR_LEN);
665
666
0
            ret = zbee_sec_ccm_decrypt(nwk_key_storage[idx].nwk_key,
667
0
                                       nonce,
668
0
                                       auth,
669
0
                                       in + payload_offset,
670
0
                                       out,
671
0
                                       sizeof(auth),
672
0
                                       *len - payload_offset - RF4CE_CCM_M,
673
0
                                       RF4CE_CCM_M);
674
675
0
            if (ret)
676
0
            {
677
0
                *len = *len - payload_offset - RF4CE_CCM_M;
678
0
                break;
679
0
            }
680
0
        }
681
682
192
        idx++;
683
192
    }
684
685
3
    return ret;
686
4
}
687
688
// Calculate the CMAC
689
void rf4ce_aes_cmac(unsigned char *input, unsigned long length, unsigned char *key, unsigned char *mac_value)
690
0
{
691
0
    gcry_mac_hd_t mac_hd;
692
0
    size_t l = length;
693
694
0
    if (gcry_mac_open(&mac_hd, GCRY_MAC_CMAC_AES, 0, NULL))
695
0
    {
696
0
        return;
697
0
    }
698
0
    if (gcry_mac_setkey(mac_hd, key, KEY_LEN))
699
0
    {
700
0
        gcry_mac_close(mac_hd);
701
0
        return;
702
0
    }
703
0
    if (gcry_mac_write(mac_hd, input, length))
704
0
    {
705
0
        gcry_mac_close(mac_hd);
706
0
        return;
707
0
    }
708
0
    if (gcry_mac_read(mac_hd, mac_value, &l))
709
0
    {
710
0
        gcry_mac_close(mac_hd);
711
0
        return;
712
0
    }
713
0
    gcry_mac_close(mac_hd);
714
0
}