Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-knxip_decrypt.c
blob8695c2b2d8cdaf47e048841b18b41ed276912ca8
1 /* packet-knxip_decrypt.c
2 * Decryption keys and decryption functions for KNX/IP Dissector
3 * Copyright 2018, ise GmbH <Ralf.Nasilowski@ise.de>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #define WS_LOG_DOMAIN "packet-knxip"
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>
25 #define TEXT_BUFFER_SIZE 128
27 #define IPA_SIZE 4 // = size of IPv4 address
29 #define BASE64_KNX_KEY_LENGTH 24 // = length of base64 encoded KNX key
31 struct knx_keyring_mca_keys* knx_keyring_mca_keys;
32 struct knx_keyring_ga_keys* knx_keyring_ga_keys;
33 struct knx_keyring_ga_senders* knx_keyring_ga_senders;
34 struct knx_keyring_ia_keys* knx_keyring_ia_keys;
35 struct knx_keyring_ia_seqs* knx_keyring_ia_seqs;
37 // Encrypt 16-byte block via AES
38 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 ] )
40 gcry_cipher_hd_t cryptor = NULL;
41 gcry_cipher_open( &cryptor, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0 );
42 gcry_cipher_setkey( cryptor, key, KNX_KEY_LENGTH );
43 gcry_cipher_encrypt( cryptor, p_crypt, KNX_KEY_LENGTH, plain, KNX_KEY_LENGTH );
44 gcry_cipher_close( cryptor );
47 // Create B_0 for CBC-MAC
48 static void build_b0( uint8_t p_result[ KNX_KEY_LENGTH ], const uint8_t* nonce, uint8_t nonce_length )
50 DISSECTOR_ASSERT( nonce_length <= KNX_KEY_LENGTH );
51 if( nonce_length ) memcpy( p_result, nonce, nonce_length );
52 memset( p_result + nonce_length, 0, KNX_KEY_LENGTH - nonce_length );
55 // Create Ctr_0 for CCM encryption/decryption
56 static void build_ctr0( uint8_t p_result[ KNX_KEY_LENGTH ], const uint8_t* nonce, uint8_t nonce_length )
58 build_b0( p_result, nonce, nonce_length );
59 p_result[ KNX_KEY_LENGTH - 2 ] = 0xFF;
62 // Calculate MAC for KNX IP Security or KNX Data Security
63 void knx_ccm_calc_cbc_mac(uint8_t p_mac[ KNX_KEY_LENGTH ], const uint8_t key[ KNX_KEY_LENGTH ],
64 const uint8_t* a_bytes, int a_length, const uint8_t* p_bytes, int p_length,
65 const uint8_t b_0[ KNX_KEY_LENGTH ] )
67 uint8_t plain[ KNX_KEY_LENGTH ];
68 uint8_t b_pos;
70 // Add B_0
71 memcpy( plain, b_0, KNX_KEY_LENGTH );
72 encrypt_block( key, plain, p_mac );
74 // Add a_length
75 plain[ 0 ] = (uint8_t) ((a_length >> 8) ^ p_mac[ 0 ]);
76 plain[ 1 ] = (uint8_t) ((a_length & 0xFF) ^ p_mac[ 1 ]);
77 b_pos = 2;
79 // Add a_bytes directly followed by p_bytes
80 while( a_length || p_length )
82 while( a_length && b_pos < KNX_KEY_LENGTH )
84 plain[ b_pos ] = *a_bytes++ ^ p_mac[ b_pos ];
85 --a_length;
86 ++b_pos;
89 while( p_length && b_pos < KNX_KEY_LENGTH )
91 plain[ b_pos ] = *p_bytes++ ^ p_mac[ b_pos ];
92 --p_length;
93 ++b_pos;
96 while( b_pos < KNX_KEY_LENGTH )
98 plain[ b_pos ] = p_mac[ b_pos ];
99 ++b_pos;
102 encrypt_block( key, plain, p_mac );
104 b_pos = 0;
108 // Calculate MAC for KNX IP Security, using 6-byte Sequence ID
109 void knxip_ccm_calc_cbc_mac( uint8_t p_mac[ KNX_KEY_LENGTH ], const uint8_t key[ KNX_KEY_LENGTH ],
110 const uint8_t* a_bytes, int a_length, const uint8_t* p_bytes, int p_length,
111 const uint8_t* nonce, uint8_t nonce_length )
113 uint8_t b_0[ KNX_KEY_LENGTH ];
114 build_b0( b_0, nonce, nonce_length );
115 b_0[ KNX_KEY_LENGTH - 2 ] = (uint8_t) (p_length >> 8);
116 b_0[ KNX_KEY_LENGTH - 1 ] = (uint8_t) (p_length & 0xFF);
117 knx_ccm_calc_cbc_mac( p_mac, key, a_bytes, a_length, p_bytes, p_length, b_0 );
120 // Encrypt for KNX IP Security or KNX Data Security
121 uint8_t* knx_ccm_encrypt( uint8_t* p_result, const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t* p_bytes, int p_length,
122 const uint8_t* mac, uint8_t mac_length, const uint8_t ctr_0[ KNX_KEY_LENGTH ], uint8_t s0_bytes_used_for_mac )
124 if( p_length >= 0 && !(p_length && !p_bytes) )
126 // NB: mac_length = 16 (for IP Security), or 4 (for Data Security)
128 uint8_t* result = p_result ? p_result : (uint8_t*) wmem_alloc( wmem_packet_scope(), p_length + mac_length );
130 uint8_t* dest = result;
132 uint8_t ctr[ KNX_KEY_LENGTH ];
133 uint8_t mask[ KNX_KEY_LENGTH ];
134 uint8_t mask_0[ KNX_KEY_LENGTH ];
135 uint8_t b_pos;
137 // Encrypt ctr_0 for mac
138 memcpy( ctr, ctr_0, KNX_KEY_LENGTH );
139 encrypt_block( key, ctr, mask_0 );
141 // Encrypt p_bytes with rest of S_0, only if mac_length < 16.
142 b_pos = s0_bytes_used_for_mac;
143 while (p_length && b_pos < KNX_KEY_LENGTH )
145 *dest++ = mask_0[b_pos++] ^ *p_bytes++;
146 --p_length;
149 // Encrypt p_bytes
150 while( p_length )
152 // Increment and encrypt ctr
153 ++ctr[ KNX_KEY_LENGTH - 1 ];
154 encrypt_block( key, ctr, mask );
156 // Encrypt input block via encrypted ctr
157 b_pos = 0;
158 while( p_length && b_pos < KNX_KEY_LENGTH )
160 *dest++ = mask[ b_pos++] ^ *p_bytes++;
161 --p_length;
165 if( mac )
167 if( mac_length > KNX_KEY_LENGTH )
169 mac_length = KNX_KEY_LENGTH;
172 // Encrypt and append mac
173 b_pos = 0;
174 while( mac_length )
176 *dest++ = mask_0[ b_pos++] ^ *mac++;
177 --mac_length;
181 return result;
184 return NULL;
187 // Encrypt for KNX IP Security (with 16-byte MAC and Nonce based on 6-byte Sequence ID)
188 uint8_t* knxip_ccm_encrypt( uint8_t* p_result, const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t* p_bytes, int p_length,
189 const uint8_t mac[KNX_KEY_LENGTH], const uint8_t* nonce, uint8_t nonce_length )
191 uint8_t ctr_0[ KNX_KEY_LENGTH ];
192 build_ctr0( ctr_0, nonce, nonce_length );
193 return knx_ccm_encrypt( p_result, key, p_bytes, p_length, mac, KNX_KEY_LENGTH, ctr_0, KNX_KEY_LENGTH );
196 // Decrypt for KNX-IP Security (with 16-byte MAC and Nonce based on 6-byte Sequence ID)
197 uint8_t* knxip_ccm_decrypt( uint8_t* p_result, const uint8_t key[ KNX_KEY_LENGTH ], const uint8_t* crypt, int crypt_length,
198 const uint8_t* nonce, uint8_t nonce_length )
200 int p_length = crypt_length - KNX_KEY_LENGTH;
201 uint8_t ctr_0[ KNX_KEY_LENGTH ];
202 build_ctr0( ctr_0, nonce, nonce_length );
203 return knx_ccm_encrypt( p_result, key, crypt, p_length, crypt + p_length, KNX_KEY_LENGTH, ctr_0, KNX_KEY_LENGTH );
206 static void fprintf_hex( FILE* f, const uint8_t* data, uint8_t length )
208 for( ; length; --length ) fprintf( f, " %02X", *data++ );
209 fputc( '\n', f );
212 static void clear_keyring_data( void )
214 while( knx_keyring_mca_keys )
216 struct knx_keyring_mca_keys* mca_key = knx_keyring_mca_keys;
217 knx_keyring_mca_keys = mca_key->next;
218 wmem_free( wmem_epan_scope(), mca_key );
221 while( knx_keyring_ga_keys )
223 struct knx_keyring_ga_keys* ga_key = knx_keyring_ga_keys;
224 knx_keyring_ga_keys = ga_key->next;
225 wmem_free( wmem_epan_scope(), ga_key );
228 while( knx_keyring_ga_senders )
230 struct knx_keyring_ga_senders* ga_sender = knx_keyring_ga_senders;
231 knx_keyring_ga_senders = ga_sender->next;
232 wmem_free( wmem_epan_scope(), ga_sender );
235 while( knx_keyring_ia_keys )
237 struct knx_keyring_ia_keys* ia_key = knx_keyring_ia_keys;
238 knx_keyring_ia_keys = ia_key->next;
239 wmem_free( wmem_epan_scope(), ia_key );
242 while( knx_keyring_ia_seqs )
244 struct knx_keyring_ia_seqs* ia_seq = knx_keyring_ia_seqs;
245 knx_keyring_ia_seqs = ia_seq->next;
246 wmem_free( wmem_epan_scope(), ia_seq );
250 // Read IP address
251 static void read_ip_addr( uint8_t result[ 4 ], const char* text )
253 ws_in4_addr value = 0;
254 if( ws_inet_pton4( text, &value ) )
255 memcpy( result, &value, 4 );
256 else
257 memset( result, 0, 4 );
260 // Read KNX group address
261 static uint16_t read_ga( const char* text )
263 unsigned a[ 3 ];
264 int n = sscanf( text, "%u/%u/%u", a, a + 1, a + 2 );
265 return
266 (n == 1) ? (uint16_t) a[ 0 ] :
267 (n == 2) ? (uint16_t) ((a[ 0 ] << 11) | a[ 1 ]) :
268 (n == 3) ? (uint16_t) ((a[ 0 ] << 11) | (a[ 1 ] << 8) | a[ 2 ]) :
272 // Read KNX individual address
273 static uint16_t read_ia( const char* text )
275 unsigned a[ 3 ];
276 int n = sscanf( text, "%u.%u.%u", a, a + 1, a + 2 );
277 return
278 (n == 1) ? (uint16_t) a[ 0 ] :
279 (n == 2) ? (uint16_t) ((a[ 0 ] << 8) | a[ 1 ]) :
280 (n == 3) ? (uint16_t) ((a[ 0 ] << 12) | (a[ 1 ] << 8) | a[ 2 ]) :
284 // Read 6-byte sequence number from decimal representation
285 static uint64_t read_seq( const char* text )
287 uint64_t result;
288 return ws_strtou64( text, NULL, &result ) ? result : 0;
291 // Decrypt key
292 static void decrypt_key( uint8_t key[] _U_, uint8_t password_hash[] _U_, uint8_t created_hash[] _U_ )
294 // TODO: decrypt as AES128-CBC(key, password_hash, created_hash)
297 // Decode and decrypt key
298 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[] )
300 size_t out_len;
301 snprintf( (char*) key, BASE64_KNX_KEY_LENGTH + 1, "%s", text );
302 g_base64_decode_inplace( (char*) key, &out_len );
303 decrypt_key( key, password_hash, created_hash );
306 // Add MCA <-> key association
307 static void add_mca_key( const uint8_t mca[ IPA_SIZE ], const char* text, uint8_t password_hash[], uint8_t created_hash[], FILE* f2 )
309 int text_length = (int) strlen( text );
311 if( text_length == BASE64_KNX_KEY_LENGTH )
313 uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ];
314 struct knx_keyring_mca_keys** mca_keys_next;
315 struct knx_keyring_mca_keys* mca_key;
317 decode_and_decrypt_key( key, text, password_hash, created_hash );
319 mca_keys_next = &knx_keyring_mca_keys;
321 while( (mca_key = *mca_keys_next) != NULL )
323 if( memcmp( mca_key->mca, mca, IPA_SIZE ) == 0 )
325 if( memcmp( mca_key->key, key, KNX_KEY_LENGTH ) == 0 )
327 return;
331 mca_keys_next = &mca_key->next;
334 if( f2 )
336 fprintf( f2, "MCA %u.%u.%u.%u key", mca[ 0 ], mca[ 1 ], mca[ 2 ], mca[ 3 ] );
337 fprintf_hex( f2, key, KNX_KEY_LENGTH );
340 mca_key = wmem_new(wmem_epan_scope(), struct knx_keyring_mca_keys);
342 if( mca_key )
344 mca_key->next = NULL;
345 memcpy( mca_key->mca, mca, IPA_SIZE );
346 memcpy( mca_key->key, key, KNX_KEY_LENGTH );
348 *mca_keys_next = mca_key;
353 // Add GA <-> key association
354 static void add_ga_key( uint16_t ga, const char* text, uint8_t password_hash[], uint8_t created_hash[], FILE* f2 )
356 int text_length = (int) strlen( text );
358 if( text_length == BASE64_KNX_KEY_LENGTH )
360 uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ];
361 struct knx_keyring_ga_keys** ga_keys_next;
362 struct knx_keyring_ga_keys* ga_key;
364 decode_and_decrypt_key( key, text, password_hash, created_hash );
366 ga_keys_next = &knx_keyring_ga_keys;
368 while( (ga_key = *ga_keys_next) != NULL )
370 if( ga_key->ga == ga )
372 if( memcmp( ga_key->key, key, KNX_KEY_LENGTH ) == 0 )
374 return;
378 ga_keys_next = &ga_key->next;
381 if( f2 )
383 fprintf( f2, "GA %u/%u/%u key", (ga >> 11) & 0x1F, (ga >> 8) & 0x7, ga & 0xFF );
384 fprintf_hex( f2, key, KNX_KEY_LENGTH );
387 ga_key = wmem_new(wmem_epan_scope(), struct knx_keyring_ga_keys);
389 if( ga_key )
391 ga_key->next = NULL;
392 ga_key->ga = ga;
393 memcpy( ga_key->key, key, KNX_KEY_LENGTH );
395 *ga_keys_next = ga_key;
400 // Add GA <-> sender association
401 static void add_ga_sender( uint16_t ga, const char* text, FILE* f2 )
403 uint16_t ia = read_ia( text );
404 struct knx_keyring_ga_senders** ga_senders_next = &knx_keyring_ga_senders;
405 struct knx_keyring_ga_senders* ga_sender;
407 while( (ga_sender = *ga_senders_next) != NULL )
409 if( ga_sender->ga == ga )
411 if( ga_sender->ia == ia )
413 return;
417 ga_senders_next = &ga_sender->next;
420 if( f2 )
422 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 );
425 ga_sender = wmem_new(wmem_epan_scope(), struct knx_keyring_ga_senders);
427 if( ga_sender )
429 ga_sender->next = NULL;
430 ga_sender->ga = ga;
431 ga_sender->ia = ia;
433 *ga_senders_next = ga_sender;
437 // Add IA <-> key association
438 static void add_ia_key( uint16_t ia, const char* text, uint8_t password_hash[], uint8_t created_hash[], FILE* f2 )
440 int text_length = (int) strlen( text );
442 if( text_length == BASE64_KNX_KEY_LENGTH )
444 uint8_t key[ BASE64_KNX_KEY_LENGTH + 1 ];
445 struct knx_keyring_ia_keys** ia_keys_next;
446 struct knx_keyring_ia_keys* ia_key;
448 decode_and_decrypt_key( key, text, password_hash, created_hash );
450 ia_keys_next = &knx_keyring_ia_keys;
452 while( (ia_key = *ia_keys_next) != NULL )
454 if( ia_key->ia == ia )
456 if( memcmp( ia_key->key, key, KNX_KEY_LENGTH ) == 0 )
458 return;
462 ia_keys_next = &ia_key->next;
465 if( f2 )
467 fprintf( f2, "IA %u.%u.%u key", (ia >> 12) & 0xF, (ia >> 8) & 0xF, ia & 0xFF );
468 fprintf_hex( f2, key, KNX_KEY_LENGTH );
471 ia_key = wmem_new(wmem_epan_scope(), struct knx_keyring_ia_keys);
473 if( ia_key )
475 ia_key->next = NULL;
476 ia_key->ia = ia;
477 memcpy( ia_key->key, key, KNX_KEY_LENGTH );
479 *ia_keys_next = ia_key;
484 // Add IA <-> sequence number association
485 static void add_ia_seq( uint16_t ia, const char* text, FILE* f2 )
487 uint64_t seq = read_seq( text );
489 struct knx_keyring_ia_seqs** ia_seqs_next = &knx_keyring_ia_seqs;
490 struct knx_keyring_ia_seqs* ia_seq;
492 while( (ia_seq = *ia_seqs_next) != NULL )
494 if( ia_seq->ia == ia )
496 if( ia_seq->seq == seq )
498 return;
502 ia_seqs_next = &ia_seq->next;
505 if( f2 )
507 fprintf( f2, "IA %u.%u.%u SeqNr %" PRIu64 "\n", (ia >> 12) & 0xF, (ia >> 8) & 0xF, ia & 0xFF, seq );
510 ia_seq = wmem_new(wmem_epan_scope(), struct knx_keyring_ia_seqs);
512 if( ia_seq )
514 ia_seq->next = NULL;
515 ia_seq->ia = ia;
516 ia_seq->seq = seq;
518 *ia_seqs_next = ia_seq;
522 // Calculate PBKDF2(HMAC-SHA256, password, "1.keyring.ets.knx.org", 65536, 128)
523 static void make_password_hash( uint8_t password_hash[] _U_, const char* password _U_ )
525 // TODO: password_hash = PBKDF2(HMAC-SHA256, password, "1.keyring.ets.knx.org", 65536, 128)
528 // Calculate MSB128(SHA256(created))
529 static void make_created_hash( uint8_t created_hash[] _U_, const char* created _U_ )
531 // TODO: created_hash = MSB128(SHA256(created))
534 // Read KNX security key info from keyring XML file.
536 // An example keyring XML file is
537 // "test/keys/knx_keyring.xml".
539 // Corresponding test is
540 // suite_decryption.case_decrypt_knxip.test_knxip_keyring_xml_import
542 // We do not use LibXml2 here, because
543 // (1) we want to be platform independent,
544 // (2) we just want to extract some data from the keyring XML file,
545 // (3) we want to avoid the complicated recursive DOM processing implied by LibXml2.
547 // Resulting decoded and decrypted 16-byte keys with context info are optionally written to a "key info" text file.
548 // This may be useful, as these keys are not directly available from the keyring XML file .
549 void read_knx_keyring_xml_file( const char* key_file, const char* password, const char* key_info_file )
551 // Clear old keyring data
552 clear_keyring_data();
554 // Read new data from keyring XML file
555 FILE* f = ws_fopen( key_file, "r" );
557 // Optionally write extracted data to key info file
558 FILE* f2 = (!key_info_file || !*key_info_file) ? NULL :
559 (strcmp( key_info_file, "-" ) == 0) ? stdout :
560 ws_fopen( key_info_file, "w" );
562 if( f )
564 uint8_t backbone_mca[ IPA_SIZE ];
565 uint8_t backbone_mca_valid = 0;
566 uint16_t group_ga = 0;
567 uint8_t group_ga_valid = 0;
568 uint16_t device_ia = 0;
569 uint8_t device_ia_valid = 0;
570 char name[ TEXT_BUFFER_SIZE ];
571 char value[ TEXT_BUFFER_SIZE ];
572 uint8_t password_hash[ KNX_KEY_LENGTH ];
573 uint8_t created_hash[ KNX_KEY_LENGTH ];
574 char tag_name[ TEXT_BUFFER_SIZE ];
575 uint8_t tag_name_done = 0;
576 uint8_t tag_end = 0;
577 uint8_t in_tag = 0;
579 memset( backbone_mca, 0, IPA_SIZE );
580 *name = '\0';
581 *value = '\0';
582 memset( password_hash, 0, KNX_KEY_LENGTH );
583 memset( created_hash, 0, KNX_KEY_LENGTH );
584 *tag_name = '\0';
586 make_password_hash( password_hash, password );
588 ws_debug( "%s:", key_file );
590 int c = fgetc( f );
592 while( c >= 0 )
594 if( c == '<' ) // tag start
596 in_tag = 1;
597 tag_end = 0;
598 *tag_name = 0;
599 tag_name_done = 0;
600 *name = '\0';
601 *value = '\0';
603 else if( c == '>' ) // tag end
605 in_tag = 0;
607 else if( c == '/' )
609 if( in_tag ) // "</" or "/>"
611 tag_end = 1;
612 *tag_name = 0;
613 tag_name_done = 0;
614 *name = '\0';
615 *value = '\0';
618 else if( g_ascii_isalpha( c ) || c == '_' ) // possibly tag name, or attribute name
620 size_t length = 0;
621 name[ length++ ] = (char) c;
622 while( (c = fgetc( f )) >= 0 )
624 if( g_ascii_isalnum( c ) || c == '_' )
626 if( length < sizeof name - 1 )
628 name[ length++ ] = (char) c;
631 else
633 break;
636 name[ length ] = '\0';
637 *value = '\0';
639 if( !tag_name_done ) // tag name
641 snprintf( tag_name, sizeof tag_name, "%s", name );
642 *name = '\0';
643 tag_name_done = 1;
645 else // Check for name="value" construct
647 while( c >= 0 && g_ascii_isspace( c ) ) c = fgetc( f );
649 if( c == '=' )
651 while( (c = fgetc( f )) >= 0 && g_ascii_isspace( c ) );
653 if( c == '"' )
655 length = 0;
657 while( (c = fgetc( f )) >= 0 )
659 if( c == '"' )
661 c = fgetc( f );
662 if( c != '"' )
664 break;
667 if( length < sizeof value - 1 )
669 value[ length++ ] = (char) c;
673 value[ length ] = 0;
675 if( !tag_end )
677 // Found name="value" construct between < and >
678 ws_debug( "%s %s=%s", tag_name, name, value );
680 // Process name/value pair
681 if( strcmp( tag_name, "Keyring" ) == 0 )
683 if( strcmp( name, "Created" ) == 0 )
685 make_created_hash( created_hash, value );
688 else if( strcmp( tag_name, "Backbone" ) == 0 )
690 group_ga_valid = 0;
691 device_ia_valid = 0;
693 if( strcmp( name, "MulticastAddress" ) == 0 )
695 read_ip_addr( backbone_mca, value );
696 backbone_mca_valid = 1;
698 else if( strcmp( name, "Key" ) == 0 )
700 if( backbone_mca_valid )
702 add_mca_key( backbone_mca, value, password_hash, created_hash, f2 );
706 else if( strcmp( tag_name, "Group" ) == 0 )
708 backbone_mca_valid = 0;
709 device_ia_valid = 0;
711 if( strcmp( name, "Address" ) == 0 )
713 group_ga = read_ga( value );
714 group_ga_valid = 1;
716 else if( strcmp( name, "Key" ) == 0 )
718 if( group_ga_valid )
720 add_ga_key( group_ga, value, password_hash, created_hash, f2 );
723 else if( strcmp( name, "Senders" ) == 0 )
725 if( group_ga_valid )
727 // Add senders given by space separated list of KNX IAs
728 static const char delim[] = " ,";
729 const char* token = strtok( value, delim );
730 while( token )
732 add_ga_sender( group_ga, token, f2 );
733 token = strtok( NULL, delim );
738 else if( strcmp( tag_name, "Device" ) == 0 )
740 backbone_mca_valid = 0;
741 group_ga_valid = 0;
743 if( strcmp( name, "IndividualAddress" ) == 0 )
745 device_ia = read_ia( value );
746 device_ia_valid = 1;
748 else if( strcmp( name, "ToolKey" ) == 0 )
750 if( device_ia_valid )
752 add_ia_key( device_ia, value, password_hash, created_hash, f2 );
755 else if( strcmp( name, "SequenceNumber" ) == 0 )
757 if( device_ia_valid )
759 add_ia_seq( device_ia, value, f2 );
763 else
765 backbone_mca_valid = 0;
766 group_ga_valid = 0;
767 device_ia_valid = 0;
774 if( c < 0 ) // EOF
776 break;
779 continue;
781 else
783 if( !g_ascii_isspace( c ) )
785 tag_name_done = 1;
786 *name = '\0';
787 *value = '\0';
791 c = fgetc( f );
794 fclose( f );
797 if( f2 && f2 != stdout )
799 fclose( f2 );
804 * Editor modelines - https://www.wireshark.org/tools/modelines.html
806 * Local variables:
807 * c-basic-offset: 2
808 * tab-width: 8
809 * indent-tabs-mode: nil
810 * End:
812 * vi: set shiftwidth=2 tabstop=8 expandtab:
813 * :indentSize=2:tabSize=8:noTabs=true: