17
17
18
18
#include <settings/settings.h>
19
19
20
+ #include <tinycrypt/constants.h>
21
+ #include <tinycrypt/utils.h>
22
+ #include <tinycrypt/aes.h>
23
+ #include <tinycrypt/cmac_mode.h>
24
+ #include <tinycrypt/ccm_mode.h>
25
+
20
26
#include <bluetooth/hci.h>
21
27
#include <bluetooth/bluetooth.h>
22
28
#include <bluetooth/conn.h>
40
46
#define SC_TIMEOUT K_MSEC(10)
41
47
#define CCC_STORE_DELAY K_SECONDS(1)
42
48
49
+ #define DB_HASH_TIMEOUT K_MSEC(10)
50
+
43
51
/* Persistent storage format for GATT CCC */
44
52
struct ccc_store {
45
53
u16_t handle ;
@@ -267,6 +275,130 @@ static ssize_t cf_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
267
275
268
276
return len ;
269
277
}
278
+
279
+ static u8_t db_hash [16 ];
280
+ struct k_delayed_work db_hash_work ;
281
+
282
+ struct gen_hash_state {
283
+ struct tc_cmac_struct state ;
284
+ int err ;
285
+ };
286
+
287
+ static u8_t gen_hash_m (const struct bt_gatt_attr * attr , void * user_data )
288
+ {
289
+ struct gen_hash_state * state = user_data ;
290
+ struct bt_uuid_16 * u16 ;
291
+ u8_t data [16 ];
292
+ size_t len ;
293
+ u16_t value ;
294
+
295
+ if (attr -> uuid -> type != BT_UUID_TYPE_16 )
296
+ return BT_GATT_ITER_CONTINUE ;
297
+
298
+ u16 = (struct bt_uuid_16 * )attr -> uuid ;
299
+
300
+ switch (u16 -> val ) {
301
+ /* Attributes to hash: handle + UUID + value */
302
+ case 0x2800 : /* GATT Primary Service */
303
+ case 0x2801 : /* GATT Secondary Service */
304
+ case 0x2802 : /* GATT Include Service */
305
+ case 0x2803 : /* GATT Characteristic */
306
+ case 0x2900 : /* GATT Characteristic Extended Properties */
307
+ value = sys_cpu_to_le16 (attr -> handle );
308
+ if (tc_cmac_update (& state -> state , (uint8_t * )& value ,
309
+ sizeof (attr -> handle )) == TC_CRYPTO_FAIL ) {
310
+ state -> err = - EINVAL ;
311
+ return BT_GATT_ITER_STOP ;
312
+ }
313
+
314
+ value = sys_cpu_to_le16 (u16 -> val );
315
+ if (tc_cmac_update (& state -> state , (uint8_t * )& value ,
316
+ sizeof (u16 -> val )) == TC_CRYPTO_FAIL ) {
317
+ state -> err = - EINVAL ;
318
+ return BT_GATT_ITER_STOP ;
319
+ }
320
+
321
+ len = attr -> read (NULL , attr , data , sizeof (data ), 0 );
322
+ if (len < 0 ) {
323
+ state -> err = len ;
324
+ return BT_GATT_ITER_STOP ;
325
+ }
326
+
327
+ if (tc_cmac_update (& state -> state , data , len ) ==
328
+ TC_CRYPTO_FAIL ) {
329
+ state -> err = - EINVAL ;
330
+ return BT_GATT_ITER_STOP ;
331
+ }
332
+
333
+ break ;
334
+ /* Attributes to hash: handle + UUID */
335
+ case 0x2901 : /* GATT Characteristic User Descriptor */
336
+ case 0x2902 : /* GATT Client Characteristic Configuration */
337
+ case 0x2903 : /* GATT Server Characteristic Configuration */
338
+ case 0x2904 : /* GATT Characteristic Presentation Format */
339
+ case 0x2905 : /* GATT Characteristic Aggregated Format */
340
+ value = sys_cpu_to_le16 (attr -> handle );
341
+ if (tc_cmac_update (& state -> state , (uint8_t * )& value ,
342
+ sizeof (attr -> handle )) == TC_CRYPTO_FAIL ) {
343
+ state -> err = - EINVAL ;
344
+ return BT_GATT_ITER_STOP ;
345
+ }
346
+
347
+ value = sys_cpu_to_le16 (u16 -> val );
348
+ if (tc_cmac_update (& state -> state , (uint8_t * )& value ,
349
+ sizeof (u16 -> val )) == TC_CRYPTO_FAIL ) {
350
+ state -> err = - EINVAL ;
351
+ return BT_GATT_ITER_STOP ;
352
+ }
353
+ break ;
354
+ default :
355
+ return BT_GATT_ITER_CONTINUE ;
356
+ }
357
+
358
+ return BT_GATT_ITER_CONTINUE ;
359
+ }
360
+
361
+ static void db_hash_gen (void )
362
+ {
363
+ u8_t key [16 ] = {};
364
+ struct tc_aes_key_sched_struct sched ;
365
+ struct gen_hash_state state ;
366
+
367
+ if (tc_cmac_setup (& state .state , key , & sched ) == TC_CRYPTO_FAIL ) {
368
+ BT_ERR ("Unable to setup AES CMAC" );
369
+ return ;
370
+ }
371
+
372
+ bt_gatt_foreach_attr (0x0001 , 0xffff , gen_hash_m , & state );
373
+
374
+ if (tc_cmac_final (db_hash , & state .state ) == TC_CRYPTO_FAIL ) {
375
+ BT_ERR ("Unable to calculate hash" );
376
+ return ;
377
+ }
378
+
379
+ BT_HEXDUMP_DBG (db_hash , sizeof (db_hash ), "Hash: " );
380
+ }
381
+
382
+ static void db_hash_process (struct k_work * work )
383
+ {
384
+ db_hash_gen ();
385
+ }
386
+
387
+ static ssize_t db_hash_read (struct bt_conn * conn ,
388
+ const struct bt_gatt_attr * attr ,
389
+ void * buf , u16_t len , u16_t offset )
390
+ {
391
+ /* Check if db_hash is already pending in which case it shall be
392
+ * generated immediately instead of waiting the work to complete.
393
+ */
394
+ if (k_delayed_work_remaining_get (& db_hash_work )) {
395
+ k_delayed_work_cancel (& db_hash_work );
396
+ db_hash_gen ();
397
+ }
398
+
399
+ return bt_gatt_attr_read (conn , attr , buf , len , offset , db_hash ,
400
+ sizeof (db_hash ));
401
+ }
270
402
#endif /* COFNIG_BT_GATT_CACHING */
271
403
272
404
static struct bt_gatt_attr gatt_attrs [] = {
@@ -284,7 +416,11 @@ static struct bt_gatt_attr gatt_attrs[] = {
284
416
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE ,
285
417
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE ,
286
418
cf_read , cf_write , NULL ),
419
+ BT_GATT_CHARACTERISTIC (BT_UUID_GATT_DB_HASH ,
420
+ BT_GATT_CHRC_READ , BT_GATT_PERM_READ ,
421
+ db_hash_read , NULL , NULL ),
287
422
#endif /* COFNIG_BT_GATT_CACHING */
423
+
288
424
};
289
425
290
426
static struct bt_gatt_service gatt_svc = BT_GATT_SERVICE (gatt_attrs );
@@ -453,6 +589,11 @@ void bt_gatt_init(void)
453
589
gatt_register (& gatt_svc );
454
590
gatt_register (& gap_svc );
455
591
592
+ #if defined(CONFIG_BT_GATT_CACHING )
593
+ k_delayed_work_init (& db_hash_work , db_hash_process );
594
+ db_hash_gen ();
595
+ #endif /* COFNIG_BT_GATT_CACHING */
596
+
456
597
k_delayed_work_init (& gatt_sc .work , sc_process );
457
598
#if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE )
458
599
k_delayed_work_init (& gatt_ccc_store .work , ccc_delayed_store );
@@ -529,6 +670,10 @@ int bt_gatt_service_register(struct bt_gatt_service *svc)
529
670
sc_indicate (& gatt_sc , svc -> attrs [0 ].handle ,
530
671
svc -> attrs [svc -> attr_count - 1 ].handle );
531
672
673
+ #if defined(CONFIG_BT_GATT_CACHING )
674
+ k_delayed_work_submit (& db_hash_work , DB_HASH_TIMEOUT );
675
+ #endif /* COFNIG_BT_GATT_CACHING */
676
+
532
677
return 0 ;
533
678
}
534
679
@@ -543,6 +688,10 @@ int bt_gatt_service_unregister(struct bt_gatt_service *svc)
543
688
sc_indicate (& gatt_sc , svc -> attrs [0 ].handle ,
544
689
svc -> attrs [svc -> attr_count - 1 ].handle );
545
690
691
+ #if defined(CONFIG_BT_GATT_CACHING )
692
+ k_delayed_work_submit (& db_hash_work , DB_HASH_TIMEOUT );
693
+ #endif /* COFNIG_BT_GATT_CACHING */
694
+
546
695
return 0 ;
547
696
}
548
697
0 commit comments