Coverage Report

Created: 2025-08-04 07:15

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