Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-knxip_decrypt.c
Line
Count
Source
1
/* packet-knxip_decrypt.c
2
 * Decryption keys and decryption functions for KNX/IP Dissector
3
 * Copyright 2018, ise GmbH <Ralf.Nasilowski@ise.de>
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 "config.h"
13
0
#define WS_LOG_DOMAIN "packet-knxip"
14
15
#include <wsutil/file_util.h>
16
#include <epan/proto.h>
17
#include "packet-knxip_decrypt.h"
18
#include <epan/wmem_scopes.h>
19
#include <wsutil/wsgcrypt.h>
20
#include <wsutil/strtoi.h>
21
#include <wsutil/wslog.h>
22
#include <wsutil/inet_addr.h>
23
#include <libxml/tree.h>
24
#include <libxml/parser.h>
25
#include <libxml/xpath.h>
26
27
#define TEXT_BUFFER_SIZE  128
28
29
0
#define IPA_SIZE  4  // = size of IPv4 address
30
31
0
#define BASE64_KNX_KEY_LENGTH  24  // = length of base64 encoded KNX key
32
33
struct knx_keyring_mca_keys* knx_keyring_mca_keys;
34
struct knx_keyring_ga_keys* knx_keyring_ga_keys;
35
struct knx_keyring_ga_senders* knx_keyring_ga_senders;
36
struct knx_keyring_ia_keys* knx_keyring_ia_keys;
37
struct knx_keyring_ia_seqs* knx_keyring_ia_seqs;
38
39
// Encrypt 16-byte block via AES
40
static bool encrypt_block( const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t plain[ KNX_KEY_LENGTH ], uint8_t p_crypt[ KNX_KEY_LENGTH ] )
41
0
{
42
0
  gcry_cipher_hd_t cryptor = NULL;
43
0
  gcry_error_t err;
44
0
  err = gcry_cipher_open( &cryptor, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0 );
45
0
  if (err != 0) {
46
0
    ws_debug("failed to open AES128 cipher handle: %s/%s", gcry_strsource(err), gcry_strerror(err));
47
0
    return false;
48
0
  }
49
0
  err = gcry_cipher_setkey( cryptor, key, KNX_KEY_LENGTH );
50
0
  if (err != 0) {
51
0
    ws_debug("failed to set AES128 cipher key: %s/%s", gcry_strsource(err), gcry_strerror(err));
52
0
    gcry_cipher_close( cryptor );
53
0
    return false;
54
0
  }
55
0
  err = gcry_cipher_encrypt( cryptor, p_crypt, KNX_KEY_LENGTH, plain, KNX_KEY_LENGTH );
56
0
  if (err != 0) {
57
0
    ws_debug("failed to encrypt AES128: %s/%s", gcry_strsource(err), gcry_strerror(err));
58
0
    gcry_cipher_close( cryptor );
59
0
    return false;
60
0
  }
61
0
  gcry_cipher_close( cryptor );
62
0
  return true;
63
0
}
64
65
// Create B_0 for CBC-MAC
66
static void build_b0( uint8_t p_result[ KNX_KEY_LENGTH ], const uint8_t* nonce, uint8_t nonce_length )
67
0
{
68
0
  DISSECTOR_ASSERT( nonce_length <= KNX_KEY_LENGTH );
69
0
  if( nonce_length ) memcpy( p_result, nonce, nonce_length );
70
0
  memset( p_result + nonce_length, 0, KNX_KEY_LENGTH - nonce_length );
71
0
}
72
73
// Create Ctr_0 for CCM encryption/decryption
74
static void build_ctr0( uint8_t p_result[ KNX_KEY_LENGTH ], const uint8_t* nonce, uint8_t nonce_length )
75
0
{
76
0
  build_b0( p_result, nonce, nonce_length );
77
0
  p_result[ KNX_KEY_LENGTH - 2 ] = 0xFF;
78
0
}
79
80
// Calculate MAC for KNX IP Security or KNX Data Security
81
void knx_ccm_calc_cbc_mac(uint8_t p_mac[ KNX_KEY_LENGTH ], const uint8_t key[ KNX_KEY_LENGTH ],
82
  const uint8_t* a_bytes, int a_length, const uint8_t* p_bytes, int p_length,
83
  const uint8_t b_0[ KNX_KEY_LENGTH ] )
84
0
{
85
0
  uint8_t plain[ KNX_KEY_LENGTH ];
86
0
  uint8_t b_pos;
87
88
  // Add B_0
89
0
  memcpy( plain, b_0, KNX_KEY_LENGTH );
90
0
  if (!encrypt_block( key, plain, p_mac )) {
91
0
    memset(p_mac, 0, KNX_KEY_LENGTH);
92
0
    return;
93
0
  }
94
95
  // Add a_length
96
0
  plain[ 0 ] = (uint8_t) ((a_length >> 8) ^ p_mac[ 0 ]);
97
0
  plain[ 1 ] = (uint8_t) ((a_length & 0xFF) ^ p_mac[ 1 ]);
98
0
  b_pos = 2;
99
100
  // Add a_bytes directly followed by p_bytes
101
0
  while( a_length || p_length )
102
0
  {
103
0
    while( a_length && b_pos < KNX_KEY_LENGTH )
104
0
    {
105
0
      plain[ b_pos ] = *a_bytes++ ^ p_mac[ b_pos ];
106
0
      --a_length;
107
0
      ++b_pos;
108
0
    }
109
110
0
    while( p_length && b_pos < KNX_KEY_LENGTH )
111
0
    {
112
0
      plain[ b_pos ] = *p_bytes++ ^ p_mac[ b_pos ];
113
0
      --p_length;
114
0
      ++b_pos;
115
0
    }
116
117
0
    while( b_pos < KNX_KEY_LENGTH )
118
0
    {
119
0
      plain[ b_pos ] = p_mac[ b_pos ];
120
0
      ++b_pos;
121
0
    }
122
123
0
    if (!encrypt_block( key, plain, p_mac )) {
124
0
      memset(p_mac, 0, KNX_KEY_LENGTH);
125
0
      return;
126
0
    }
127
128
0
    b_pos = 0;
129
0
  }
130
0
}
131
132
// Calculate MAC for KNX IP Security, using 6-byte Sequence ID
133
void knxip_ccm_calc_cbc_mac( uint8_t p_mac[ KNX_KEY_LENGTH ], const uint8_t key[ KNX_KEY_LENGTH ],
134
  const uint8_t* a_bytes, int a_length, const uint8_t* p_bytes, int p_length,
135
  const uint8_t* nonce, uint8_t nonce_length )
136
0
{
137
0
  uint8_t b_0[ KNX_KEY_LENGTH ];
138
0
  build_b0( b_0, nonce, nonce_length );
139
0
  b_0[ KNX_KEY_LENGTH - 2 ] = (uint8_t) (p_length >> 8);
140
0
  b_0[ KNX_KEY_LENGTH - 1 ] = (uint8_t) (p_length & 0xFF);
141
0
  knx_ccm_calc_cbc_mac( p_mac, key, a_bytes, a_length, p_bytes, p_length, b_0 );
142
0
}
143
144
// Encrypt for KNX IP Security or KNX Data Security
145
uint8_t* knx_ccm_encrypt(wmem_allocator_t* scope, uint8_t* p_result, const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t* p_bytes, int p_length,
146
  const uint8_t* mac, uint8_t mac_length, const uint8_t ctr_0[ KNX_KEY_LENGTH ], uint8_t s0_bytes_used_for_mac )
147
0
{
148
0
  if( p_length >= 0 && !(p_length && !p_bytes) )
149
0
  {
150
    // NB: mac_length = 16 (for IP Security), or 4 (for Data Security)
151
152
0
    uint8_t* result = p_result ? p_result : (uint8_t*) wmem_alloc(scope, p_length + mac_length );
153
154
0
    uint8_t* dest = result;
155
156
0
    uint8_t ctr[ KNX_KEY_LENGTH ];
157
0
    uint8_t mask[ KNX_KEY_LENGTH ];
158
0
    uint8_t mask_0[ KNX_KEY_LENGTH ];
159
0
    uint8_t b_pos;
160
161
    // Encrypt ctr_0 for mac
162
0
    memcpy( ctr, ctr_0, KNX_KEY_LENGTH );
163
0
    if (!encrypt_block( key, ctr, mask_0 )) {
164
0
      if (!p_result) wmem_free(scope, result);
165
0
      return NULL;
166
0
    }
167
168
    // Encrypt p_bytes with rest of S_0, only if mac_length < 16.
169
0
    b_pos = s0_bytes_used_for_mac;
170
0
    while (p_length && b_pos < KNX_KEY_LENGTH )
171
0
    {
172
0
      *dest++ = mask_0[b_pos++] ^ *p_bytes++;
173
0
      --p_length;
174
0
    }
175
176
    // Encrypt p_bytes
177
0
    while( p_length )
178
0
    {
179
      // Increment and encrypt ctr
180
0
      ++ctr[ KNX_KEY_LENGTH - 1 ];
181
0
      if (!encrypt_block( key, ctr, mask )) {
182
0
        if (!p_result) wmem_free(scope, result);
183
0
        return NULL;
184
0
      }
185
186
      // Encrypt input block via encrypted ctr
187
0
      b_pos = 0;
188
0
      while( p_length && b_pos < KNX_KEY_LENGTH )
189
0
      {
190
0
        *dest++ = mask[ b_pos++] ^ *p_bytes++;
191
0
        --p_length;
192
0
      }
193
0
    }
194
195
0
    if( mac )
196
0
    {
197
0
      if( mac_length > KNX_KEY_LENGTH )
198
0
      {
199
0
        mac_length = KNX_KEY_LENGTH;
200
0
      }
201
202
      // Encrypt and append mac
203
0
      b_pos = 0;
204
0
      while( mac_length )
205
0
      {
206
0
        *dest++ = mask_0[ b_pos++] ^ *mac++;
207
0
        --mac_length;
208
0
      }
209
0
    }
210
211
0
    return result;
212
0
  }
213
214
0
  return NULL;
215
0
}
216
217
// Encrypt for KNX IP Security (with 16-byte MAC and Nonce based on 6-byte Sequence ID)
218
uint8_t* knxip_ccm_encrypt(wmem_allocator_t* scope, uint8_t* p_result, const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t* p_bytes, int p_length,
219
  const uint8_t mac[KNX_KEY_LENGTH], const uint8_t* nonce, uint8_t nonce_length )
220
0
{
221
0
  uint8_t ctr_0[ KNX_KEY_LENGTH ];
222
0
  build_ctr0( ctr_0, nonce, nonce_length );
223
0
  return knx_ccm_encrypt(scope, p_result, key, p_bytes, p_length, mac, KNX_KEY_LENGTH, ctr_0, KNX_KEY_LENGTH );
224
0
}
225
226
// Decrypt for KNX-IP Security (with 16-byte MAC and Nonce based on 6-byte Sequence ID)
227
uint8_t* knxip_ccm_decrypt(wmem_allocator_t* scope, uint8_t* p_result, const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t* crypt, int crypt_length,
228
  const uint8_t* nonce, uint8_t nonce_length )
229
0
{
230
0
  int p_length = crypt_length - KNX_KEY_LENGTH;
231
0
  uint8_t ctr_0[ KNX_KEY_LENGTH ];
232
0
  build_ctr0( ctr_0, nonce, nonce_length );
233
0
  return knx_ccm_encrypt(scope, p_result, key, crypt, p_length, crypt + p_length, KNX_KEY_LENGTH, ctr_0, KNX_KEY_LENGTH );
234
0
}
235
236
static void fprintf_hex( FILE* f, const uint8_t* data, uint8_t length )
237
0
{
238
0
  for( ; length; --length ) fprintf( f, " %02X", *data++ );
239
0
  fputc( '\n', f );
240
0
}
241
242
static void clear_keyring_data( void )
243
0
{
244
0
  while( knx_keyring_mca_keys )
245
0
  {
246
0
    struct knx_keyring_mca_keys* mca_key = knx_keyring_mca_keys;
247
0
    knx_keyring_mca_keys = mca_key->next;
248
0
    wmem_free( wmem_epan_scope(), mca_key );
249
0
  }
250
251
0
  while( knx_keyring_ga_keys )
252
0
  {
253
0
    struct knx_keyring_ga_keys* ga_key = knx_keyring_ga_keys;
254
0
    knx_keyring_ga_keys = ga_key->next;
255
0
    wmem_free( wmem_epan_scope(), ga_key );
256
0
  }
257
258
0
  while( knx_keyring_ga_senders )
259
0
  {
260
0
    struct knx_keyring_ga_senders* ga_sender = knx_keyring_ga_senders;
261
0
    knx_keyring_ga_senders = ga_sender->next;
262
0
    wmem_free( wmem_epan_scope(), ga_sender );
263
0
  }
264
265
0
  while( knx_keyring_ia_keys )
266
0
  {
267
0
    struct knx_keyring_ia_keys* ia_key = knx_keyring_ia_keys;
268
0
    knx_keyring_ia_keys = ia_key->next;
269
0
    wmem_free( wmem_epan_scope(), ia_key );
270
0
  }
271
272
0
  while( knx_keyring_ia_seqs )
273
0
  {
274
0
    struct knx_keyring_ia_seqs* ia_seq = knx_keyring_ia_seqs;
275
0
    knx_keyring_ia_seqs = ia_seq->next;
276
0
    wmem_free( wmem_epan_scope(), ia_seq );
277
0
  }
278
0
}
279
280
// Read IP address
281
static void read_ip_addr( uint8_t result[ 4 ], const char* text )
282
0
{
283
0
  ws_in4_addr value = 0;
284
0
  if( ws_inet_pton4( text, &value ) )
285
0
    memcpy( result, &value, 4 );
286
0
  else
287
0
    memset( result, 0, 4 );
288
0
}
289
290
// Read KNX group address
291
static uint16_t read_ga( const char* text )
292
0
{
293
0
  unsigned a[ 3 ];
294
0
  int n = sscanf( text, "%u/%u/%u", a, a + 1, a + 2 );
295
0
  return
296
0
    (n == 1) ? (uint16_t) a[ 0 ] :
297
0
    (n == 2) ? (uint16_t) ((a[ 0 ] << 11) | a[ 1 ]) :
298
0
    (n == 3) ? (uint16_t) ((a[ 0 ] << 11) | (a[ 1 ] << 8) | a[ 2 ]) :
299
0
    0;
300
0
}
301
302
// Read KNX individual address
303
static uint16_t read_ia( const char* text )
304
0
{
305
0
  unsigned a[ 3 ];
306
0
  int n = sscanf( text, "%u.%u.%u", a, a + 1, a + 2 );
307
0
  return
308
0
    (n == 1) ? (uint16_t) a[ 0 ] :
309
0
    (n == 2) ? (uint16_t) ((a[ 0 ] << 8) | a[ 1 ]) :
310
0
    (n == 3) ? (uint16_t) ((a[ 0 ] << 12) | (a[ 1 ] << 8) | a[ 2 ]) :
311
0
    0;
312
0
}
313
314
// Read 6-byte sequence number from decimal representation
315
static uint64_t read_seq( const char* text )
316
0
{
317
0
  uint64_t result;
318
0
  return ws_strtou64( text, NULL, &result ) ? result : 0;
319
0
}
320
321
// Decrypt key
322
static void decrypt_key( uint8_t key[] _U_, uint8_t password_hash[] _U_, uint8_t created_hash[] _U_ )
323
0
{
324
  // TODO: decrypt as AES128-CBC(key, password_hash, created_hash)
325
0
}
326
327
// Decode and decrypt key
328
static void decode_and_decrypt_key( uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ], const char* text, uint8_t password_hash[], uint8_t created_hash[] )
329
0
{
330
0
  size_t out_len;
331
0
  snprintf( (char*) key, BASE64_KNX_KEY_LENGTH + 1, "%s", text );
332
0
  g_base64_decode_inplace( (char*) key, &out_len );
333
0
  decrypt_key( key, password_hash, created_hash );
334
0
}
335
336
// Add MCA <-> key association
337
static void add_mca_key( const uint8_t mca[ IPA_SIZE ], const char* text, uint8_t password_hash[], uint8_t created_hash[], FILE* f2 )
338
0
{
339
0
  int text_length = (int) strlen( text );
340
341
0
  if( text_length == BASE64_KNX_KEY_LENGTH )
342
0
  {
343
0
    uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ];
344
0
    struct knx_keyring_mca_keys** mca_keys_next;
345
0
    struct knx_keyring_mca_keys* mca_key;
346
347
0
    decode_and_decrypt_key( key, text, password_hash, created_hash );
348
349
0
    mca_keys_next = &knx_keyring_mca_keys;
350
351
0
    while( (mca_key = *mca_keys_next) != NULL )
352
0
    {
353
0
      if( memcmp( mca_key->mca, mca, IPA_SIZE ) == 0 )
354
0
      {
355
0
        if( memcmp( mca_key->key, key, KNX_KEY_LENGTH ) == 0 )
356
0
        {
357
0
          return;
358
0
        }
359
0
      }
360
361
0
      mca_keys_next = &mca_key->next;
362
0
    }
363
364
0
    if( f2 )
365
0
    {
366
0
      fprintf( f2, "MCA %u.%u.%u.%u key", mca[ 0 ], mca[ 1 ], mca[ 2 ], mca[ 3 ] );
367
0
      fprintf_hex( f2, key, KNX_KEY_LENGTH );
368
0
    }
369
370
0
    mca_key = wmem_new(wmem_epan_scope(), struct knx_keyring_mca_keys);
371
372
0
    if( mca_key )
373
0
    {
374
0
      mca_key->next = NULL;
375
0
      memcpy( mca_key->mca, mca, IPA_SIZE );
376
0
      memcpy( mca_key->key, key, KNX_KEY_LENGTH );
377
378
0
      *mca_keys_next = mca_key;
379
0
    }
380
0
  }
381
0
}
382
383
// Add GA <-> key association
384
static void add_ga_key( uint16_t ga, const char* text, uint8_t password_hash[], uint8_t created_hash[], FILE* f2 )
385
0
{
386
0
  int text_length = (int) strlen( text );
387
388
0
  if( text_length == BASE64_KNX_KEY_LENGTH )
389
0
  {
390
0
    uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ];
391
0
    struct knx_keyring_ga_keys** ga_keys_next;
392
0
    struct knx_keyring_ga_keys* ga_key;
393
394
0
    decode_and_decrypt_key( key, text, password_hash, created_hash );
395
396
0
    ga_keys_next = &knx_keyring_ga_keys;
397
398
0
    while( (ga_key = *ga_keys_next) != NULL )
399
0
    {
400
0
      if( ga_key->ga == ga )
401
0
      {
402
0
        if( memcmp( ga_key->key, key, KNX_KEY_LENGTH ) == 0 )
403
0
        {
404
0
          return;
405
0
        }
406
0
      }
407
408
0
      ga_keys_next = &ga_key->next;
409
0
    }
410
411
0
    if( f2 )
412
0
    {
413
0
      fprintf( f2, "GA %d/%d/%d key", (ga >> 11) & 0x1F, (ga >> 8) & 0x7, ga & 0xFF );
414
0
      fprintf_hex( f2, key, KNX_KEY_LENGTH );
415
0
    }
416
417
0
    ga_key = wmem_new(wmem_epan_scope(), struct knx_keyring_ga_keys);
418
419
0
    if( ga_key )
420
0
    {
421
0
      ga_key->next = NULL;
422
0
      ga_key->ga = ga;
423
0
      memcpy( ga_key->key, key, KNX_KEY_LENGTH );
424
425
0
      *ga_keys_next = ga_key;
426
0
    }
427
0
  }
428
0
}
429
430
// Add GA <-> sender association
431
static void add_ga_sender( uint16_t ga, const char* text, FILE* f2 )
432
0
{
433
0
  uint16_t ia = read_ia( text );
434
0
  struct knx_keyring_ga_senders** ga_senders_next = &knx_keyring_ga_senders;
435
0
  struct knx_keyring_ga_senders* ga_sender;
436
437
0
  while( (ga_sender = *ga_senders_next) != NULL )
438
0
  {
439
0
    if( ga_sender->ga == ga )
440
0
    {
441
0
      if( ga_sender->ia == ia )
442
0
      {
443
0
        return;
444
0
      }
445
0
    }
446
447
0
    ga_senders_next = &ga_sender->next;
448
0
  }
449
450
0
  if( f2 )
451
0
  {
452
0
    fprintf( f2, "GA %d/%d/%d sender %d.%d.%d\n", (ga >> 11) & 0x1F, (ga >> 8) & 0x7, ga & 0xFF, (ia >> 12) & 0xF, (ia >> 8) & 0xF, ia & 0xFF );
453
0
  }
454
455
0
  ga_sender = wmem_new(wmem_epan_scope(), struct knx_keyring_ga_senders);
456
457
0
  if( ga_sender )
458
0
  {
459
0
    ga_sender->next = NULL;
460
0
    ga_sender->ga = ga;
461
0
    ga_sender->ia = ia;
462
463
0
    *ga_senders_next = ga_sender;
464
0
  }
465
0
}
466
467
// Add IA <-> key association
468
static void add_ia_key( uint16_t ia, const char* text, uint8_t password_hash[], uint8_t created_hash[], FILE* f2 )
469
0
{
470
0
  int text_length = (int) strlen( text );
471
472
0
  if( text_length == BASE64_KNX_KEY_LENGTH )
473
0
  {
474
0
    uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ];
475
0
    struct knx_keyring_ia_keys** ia_keys_next;
476
0
    struct knx_keyring_ia_keys* ia_key;
477
478
0
    decode_and_decrypt_key( key, text, password_hash, created_hash );
479
480
0
    ia_keys_next = &knx_keyring_ia_keys;
481
482
0
    while( (ia_key = *ia_keys_next) != NULL )
483
0
    {
484
0
      if( ia_key->ia == ia )
485
0
      {
486
0
        if( memcmp( ia_key->key, key, KNX_KEY_LENGTH ) == 0 )
487
0
        {
488
0
          return;
489
0
        }
490
0
      }
491
492
0
      ia_keys_next = &ia_key->next;
493
0
    }
494
495
0
    if( f2 )
496
0
    {
497
0
      fprintf( f2, "IA %d.%d.%d key", (ia >> 12) & 0xF, (ia >> 8) & 0xF, ia & 0xFF );
498
0
      fprintf_hex( f2, key, KNX_KEY_LENGTH );
499
0
    }
500
501
0
    ia_key = wmem_new(wmem_epan_scope(), struct knx_keyring_ia_keys);
502
503
0
    if( ia_key )
504
0
    {
505
0
      ia_key->next = NULL;
506
0
      ia_key->ia = ia;
507
0
      memcpy( ia_key->key, key, KNX_KEY_LENGTH );
508
509
0
      *ia_keys_next = ia_key;
510
0
    }
511
0
  }
512
0
}
513
514
// Add IA <-> sequence number association
515
static void add_ia_seq( uint16_t ia, const char* text, FILE* f2 )
516
0
{
517
0
  uint64_t seq = read_seq( text );
518
519
0
  struct knx_keyring_ia_seqs** ia_seqs_next = &knx_keyring_ia_seqs;
520
0
  struct knx_keyring_ia_seqs* ia_seq;
521
522
0
  while( (ia_seq = *ia_seqs_next) != NULL )
523
0
  {
524
0
    if( ia_seq->ia == ia )
525
0
    {
526
0
      if( ia_seq->seq == seq )
527
0
      {
528
0
        return;
529
0
      }
530
0
    }
531
532
0
    ia_seqs_next = &ia_seq->next;
533
0
  }
534
535
0
  if( f2 )
536
0
  {
537
0
    fprintf( f2, "IA %u.%u.%u SeqNr %" PRIu64 "\n", (ia >> 12) & 0xF, (ia >> 8) & 0xF, ia & 0xFF, seq );
538
0
  }
539
540
0
  ia_seq = wmem_new(wmem_epan_scope(), struct knx_keyring_ia_seqs);
541
542
0
  if( ia_seq )
543
0
  {
544
0
    ia_seq->next = NULL;
545
0
    ia_seq->ia = ia;
546
0
    ia_seq->seq = seq;
547
548
0
    *ia_seqs_next = ia_seq;
549
0
  }
550
0
}
551
552
// Calculate PBKDF2(HMAC-SHA256, password, "1.keyring.ets.knx.org", 65536, 128)
553
static void make_password_hash( uint8_t password_hash[] _U_, const char* password _U_ )
554
0
{
555
  // TODO: password_hash = PBKDF2(HMAC-SHA256, password, "1.keyring.ets.knx.org", 65536, 128)
556
0
}
557
558
// Calculate MSB128(SHA256(created))
559
static void make_created_hash( uint8_t created_hash[] _U_, const char* created _U_ )
560
0
{
561
  // TODO: created_hash = MSB128(SHA256(created))
562
0
}
563
564
static void read_knx_keyring_xml_backbone_element(xmlNodePtr backbone, uint8_t password_hash[], uint8_t created_hash[], FILE* f2)
565
0
{
566
0
  bool address_valid = false;
567
0
  uint8_t multicast_address[IPA_SIZE] = { 0 };
568
569
  /* Parse out the attributes of the Backbone element */
570
0
  for (xmlAttrPtr attr = backbone->properties; attr; attr = attr->next)
571
0
  {
572
0
    if (xmlStrcmp(attr->name, (const xmlChar*)"MulticastAddress") == 0)
573
0
    {
574
0
      xmlChar* str_address = xmlNodeListGetString(backbone->doc, attr->children, 1);
575
0
      if (str_address != NULL)
576
0
      {
577
0
        read_ip_addr(multicast_address, (const char*)str_address);
578
0
        address_valid = true;
579
0
        xmlFree(str_address);
580
0
      }
581
0
    }
582
0
    else if (xmlStrcmp(attr->name, (const xmlChar*)"Key") == 0)
583
0
    {
584
0
      if (address_valid)
585
0
      {
586
0
        xmlChar* str_key = xmlNodeListGetString(backbone->doc, attr->children, 1);
587
0
        if (str_key != NULL)
588
0
        {
589
0
          add_mca_key(multicast_address, (const char*)str_key, password_hash, created_hash, f2);
590
0
          xmlFree(str_key);
591
0
        }
592
0
      }
593
0
    }
594
0
  }
595
596
0
}
597
598
static void read_knx_keyring_xml_group_element(xmlNodePtr group, uint8_t password_hash[], uint8_t created_hash[], FILE* f2)
599
0
{
600
0
  bool address_valid = false;
601
0
  uint16_t addr = 0;
602
603
  /* Parse out the attributes of the Group element */
604
0
  for (xmlAttrPtr attr = group->properties; attr; attr = attr->next)
605
0
  {
606
0
      if (xmlStrcmp(attr->name, (const xmlChar*)"Address") == 0)
607
0
      {
608
0
        xmlChar* str_address = xmlNodeListGetString(group->doc, attr->children, 1);
609
0
        if (str_address != NULL)
610
0
        {
611
0
          addr = read_ga((const char*)str_address);
612
0
          address_valid = true;
613
0
          xmlFree(str_address);
614
0
        }
615
0
      }
616
0
      else if (xmlStrcmp(attr->name, (const xmlChar*)"Key") == 0)
617
0
      {
618
0
        if (address_valid)
619
0
        {
620
0
          xmlChar* str_key = xmlNodeListGetString(group->doc, attr->children, 1);
621
0
          add_ga_key(addr, (const char*)str_key, password_hash, created_hash, f2);
622
0
          xmlFree(str_key);
623
0
          }
624
0
        }
625
0
        else if (xmlStrcmp(attr->name, (const xmlChar*)"Senders") == 0)
626
0
        {
627
0
          if (address_valid)
628
0
          {
629
0
            xmlChar* str_senders = xmlNodeListGetString(group->doc, attr->children, 1);
630
0
            if (str_senders != NULL)
631
0
            {
632
              // Add senders given by space separated list of KNX IAs
633
0
              static const char delim[] = " ,";
634
0
              const char* token = strtok((char*)str_senders, delim);
635
0
              while (token)
636
0
              {
637
0
                add_ga_sender(addr, token, f2);
638
0
                token = strtok(NULL, delim);
639
0
              }
640
0
              xmlFree(str_senders);
641
0
          }
642
0
        }
643
0
      }
644
0
    }
645
646
0
}
647
648
static void read_knx_keyring_xml_device_element(xmlNodePtr device, uint8_t password_hash[], uint8_t created_hash[], FILE* f2)
649
0
{
650
0
  bool address_valid = false;
651
0
  uint16_t addr = 0;
652
653
  /* Parse out the attributes of the Device element */
654
0
  for (xmlAttrPtr attr = device->properties; attr; attr = attr->next)
655
0
  {
656
0
    if (xmlStrcmp(attr->name, (const xmlChar*)"IndividualAddress") == 0)
657
0
    {
658
0
      xmlChar* str_address = xmlNodeListGetString(device->doc, attr->children, 1);
659
0
      if (str_address != NULL)
660
0
      {
661
0
        addr = read_ia((const char*)str_address);
662
0
        address_valid = true;
663
0
        xmlFree(str_address);
664
0
      }
665
0
    }
666
0
    else if (xmlStrcmp(attr->name, (const xmlChar*)"ToolKey") == 0)
667
0
    {
668
0
      if (address_valid)
669
0
      {
670
0
        xmlChar* str_key = xmlNodeListGetString(device->doc, attr->children, 1);
671
0
        if (str_key != NULL)
672
0
        {
673
0
          add_ia_key(addr, (const char*)str_key, password_hash, created_hash, f2);
674
0
          xmlFree(str_key);
675
0
        }
676
0
      }
677
0
    }
678
0
    else if (xmlStrcmp(attr->name, (const xmlChar*)"SequenceNumber") == 0)
679
0
    {
680
0
      if (address_valid)
681
0
      {
682
0
        xmlChar* str_seq = xmlNodeListGetString(device->doc, attr->children, 1);
683
0
        if (str_seq != NULL)
684
0
        {
685
0
          add_ia_seq(addr, (const char*)str_seq, f2);
686
0
          xmlFree(str_seq);
687
0
        }
688
0
      }
689
0
    }
690
0
  }
691
0
}
692
693
// Read KNX security key info from keyring XML file.
694
//
695
// An example keyring XML file is
696
//   "test/keys/knx_keyring.xml".
697
//
698
// Corresponding test is
699
//   suite_decryption.case_decrypt_knxip.test_knxip_keyring_xml_import
700
//
701
// Resulting decoded and decrypted 16-byte keys with context info are optionally written to a "key info" text file.
702
// This may be useful, as these keys are not directly available from the keyring XML file .
703
void read_knx_keyring_xml_file(const char* key_file, const char* password, const char* key_info_file)
704
0
{
705
0
  xmlDocPtr doc;
706
0
  xmlNodePtr root_element = NULL;
707
0
  xmlNodePtr key_ring = NULL;
708
0
  uint8_t password_hash[KNX_KEY_LENGTH] = { 0 };
709
0
  uint8_t created_hash[KNX_KEY_LENGTH] = {0};
710
711
  // Clear old keyring data
712
0
  clear_keyring_data();
713
714
0
  doc = xmlReadFile(key_file, NULL, 0);
715
0
  if (doc == NULL)
716
0
    return;
717
718
0
  root_element = xmlDocGetRootElement(doc);
719
0
  if (root_element == NULL)
720
0
  {
721
0
    xmlFreeDoc(doc);
722
0
    return;
723
0
  }
724
725
  /* Find the Keyring element */
726
0
  if (xmlStrcmp(root_element->name, (const xmlChar*)"Keyring") == 0)
727
0
  {
728
0
    key_ring = root_element;
729
0
  }
730
0
  else
731
0
  {
732
0
    for (xmlNodePtr cur = root_element->children; cur != NULL; cur = cur->next)
733
0
    {
734
0
      if (cur->type == XML_ELEMENT_NODE && xmlStrcmp(cur->name, (const xmlChar*)"Keyring") == 0)
735
0
      {
736
0
        key_ring = cur;
737
0
        break;
738
0
      }
739
0
    }
740
0
  }
741
742
0
  if (key_ring == NULL) {
743
0
    xmlFreeDoc(doc);
744
0
    return;
745
0
  }
746
747
  // Optionally write extracted data to key info file
748
0
  FILE* f2 = (!key_info_file || !*key_info_file) ? NULL :
749
0
    (strcmp( key_info_file, "-" ) == 0) ? stdout :
750
0
    ws_fopen( key_info_file, "w" );
751
752
0
  make_password_hash(password_hash, password);
753
754
  /* Parse out the attributes of the Keyring element */
755
0
  for (xmlAttrPtr attr = key_ring->properties; attr; attr = attr->next)
756
0
  {
757
0
    if (xmlStrcmp(attr->name, (const xmlChar*)"Created") == 0)
758
0
    {
759
0
      xmlChar* str_created = xmlNodeListGetString(key_ring->doc, attr->children, 1);
760
0
      if (str_created != NULL)
761
0
       {
762
0
         make_created_hash(created_hash, (const char*)str_created);
763
0
         xmlFree(str_created);
764
0
       }
765
0
    }
766
0
  }
767
768
  /* Parse out subelements of Keyring element */
769
0
  for (xmlNodePtr cur = key_ring->children; cur != NULL; cur = cur->next)
770
0
  {
771
0
    if (cur->type == XML_ELEMENT_NODE && xmlStrcmp(cur->name, (const xmlChar*)"Backbone") == 0)
772
0
    {
773
0
      read_knx_keyring_xml_backbone_element(cur, password_hash, created_hash, f2);
774
0
    }
775
0
    else if (cur->type == XML_ELEMENT_NODE && xmlStrcmp(cur->name, (const xmlChar*)"Interface") == 0)
776
0
    {
777
0
      for (xmlNodePtr group = cur->children; group != NULL; group = group->next)
778
0
      {
779
0
        if (group->type == XML_ELEMENT_NODE && xmlStrcmp(group->name, (const xmlChar*)"Group") == 0)
780
0
        {
781
0
          read_knx_keyring_xml_group_element(group, password_hash, created_hash, f2);
782
0
        }
783
0
      }
784
0
    }
785
0
    else if (cur->type == XML_ELEMENT_NODE && xmlStrcmp(cur->name, (const xmlChar*)"GroupAddresses") == 0)
786
0
    {
787
0
      for (xmlNodePtr group = cur->children; group != NULL; group = group->next)
788
0
      {
789
0
        if (group->type == XML_ELEMENT_NODE && xmlStrcmp(group->name, (const xmlChar*)"Group") == 0)
790
0
        {
791
0
          read_knx_keyring_xml_group_element(group, password_hash, created_hash, f2);
792
0
        }
793
0
      }
794
0
    }
795
0
    else if (cur->type == XML_ELEMENT_NODE && xmlStrcmp(cur->name, (const xmlChar*)"Devices") == 0)
796
0
    {
797
0
      for (xmlNodePtr device = cur->children; device != NULL; device = device->next)
798
0
      {
799
0
        if (device->type == XML_ELEMENT_NODE && xmlStrcmp(device->name, (const xmlChar*)"Device") == 0)
800
0
        {
801
0
          read_knx_keyring_xml_device_element(device, password_hash, created_hash, f2);
802
0
        }
803
0
      }
804
0
    }
805
0
  }
806
807
0
  if (f2 && f2 != stdout)
808
0
    fclose(f2);
809
0
  xmlFreeDoc(doc);
810
0
}
811
812
/*
813
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
814
 *
815
 * Local variables:
816
 * c-basic-offset: 2
817
 * tab-width: 8
818
 * indent-tabs-mode: nil
819
 * End:
820
 *
821
 * vi: set shiftwidth=2 tabstop=8 expandtab:
822
 * :indentSize=2:tabSize=8:noTabs=true:
823
 */