1 /* packet-corosync-totemnet.c
2 * Dissector routines for the lowest level(encryption/decryption) protocol used in Corosync cluster engine
3 * Copyright 2009 2010 2014 Masatake YAMATO <yamato@redhat.com>
4 * Copyright (c) 2010 2014 Red Hat, Inc.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <wsutil/wsgcrypt.h>
18 #include <wsutil/sober128.h>
20 static dissector_handle_t corosync_totemnet_handle
;
21 static dissector_handle_t corosync_totemsrp_handle
;
23 /* This dissector deals packets defined in totemnet.c of corosync
24 cluster engine. In the totemnet.c the packet is encrypted and decrypted
25 with LibTomCrypt. This dissector tries decrypting the packet with
26 sober128 and sha1 functions in wireshark. */
32 #define PORT_COROSYNC_TOTEMNET_RANGE "5404-5405" /* Not IANA registered */
34 /* Forward declaration we need below */
35 void proto_register_corosync_totemnet(void);
36 void proto_reg_handoff_corosync_totemnet(void);
38 /* Initialize the protocol and registered fields */
39 static int proto_corosync_totemnet
;
41 /* field of struct security_header */
42 static int hf_corosync_totemnet_security_header_hash_digest
;
43 static int hf_corosync_totemnet_security_header_salt
;
44 static int hf_corosync_totemnet_security_crypto_type
;
45 static int hf_corosync_totemnet_security_crypto_key
;
47 /* configurable parameters */
48 static char* corosync_totemnet_private_keys
;
49 static char** corosync_totemnet_private_keys_list
;
51 /* Initialize the subtree pointers */
52 static int ett_corosync_totemnet_security_header
;
56 #define TOTEM_CRYPTO_SOBER 0
57 #define TOTEM_CRYPTO_NSS 1
59 static const value_string corosync_totemnet_crypto_type
[] = {
60 { TOTEM_CRYPTO_SOBER
, "SOBER" },
61 { TOTEM_CRYPTO_NSS
, "NSS" },
67 dissect_corosync_totemnet_security_header(tvbuff_t
*tvb
,
68 packet_info
*pinfo
, proto_tree
*parent_tree
,
69 bool check_crypt_type
,
75 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "COROSYNC/TOTEMNET");
76 col_clear(pinfo
->cinfo
, COL_INFO
);
80 item
= proto_tree_add_item(parent_tree
, proto_corosync_totemnet
, tvb
, 0,
82 tree
= proto_item_add_subtree(item
, ett_corosync_totemnet_security_header
);
84 proto_tree_add_item(tree
,
85 hf_corosync_totemnet_security_header_hash_digest
,
86 tvb
, 0, HASH_SHA1_LENGTH
, ENC_NA
);
87 proto_tree_add_item(tree
,
88 hf_corosync_totemnet_security_header_salt
,
89 tvb
, HASH_SHA1_LENGTH
, SALT_SIZE
, ENC_NA
);
93 int io_len
= tvb_reported_length(tvb
);
94 proto_item
* key_item
;
96 proto_tree_add_item(tree
,
97 hf_corosync_totemnet_security_crypto_type
,
98 tvb
, io_len
- 1, 1, ENC_BIG_ENDIAN
);
99 key_item
= proto_tree_add_string(tree
,
100 hf_corosync_totemnet_security_crypto_key
,
102 proto_item_set_generated(key_item
);
105 return HASH_SHA1_LENGTH
+ SALT_SIZE
;
108 /* About totemnet.c of corosync cluster engine:
110 * dissect_corosynec_totemnet_with_decryption() is derived from
111 * totemnet.c in corosync which is licensed under 3-clause BSD license.
112 * However, to merge this dissector to wireshark official source tree,
113 * corosync developers permit EXPLICITLY to reuse totemnet.c in GPL.
115 http://permalink.gmane.org/gmane.linux.redhat.cluster/19087
116 ------------------------------------------------------------
117 Steven Dake | 4 Jan 2011 22:02
118 Re: [Openais] packet dissectors for totempg, cman, clvmd, rgmanager, cpg,
120 On 12/14/2010 08:04 AM, Masatake YAMATO wrote:
121 > Thank you for replying.
125 >> Masatake YAMATO napsal(a):
126 >>> I'd like to your advice more detail seriously.
127 >>> I've been developing this code for three years.
128 >>> I don't want to make this code garbage.
131 >>>> I'm pretty sure that biggest problem of your code was that it was
132 >>>> licensed under BSD (three clause, same as Corosync has)
133 >>>> license. Wireshark is licensed under GPL and even I like BSD licenses
134 >>>> much more, I would recommend you to try to relicense code under GPL
135 >>>> and send them this code.
139 >>> I got the similar comment from wireshark developer.
140 >>> Please, read the discussion:
141 >>> https://gitlab.com/wireshark/wireshark/-/issues/3232
144 >> I've read that thread long time before I've sent previous mail, so
145 >> thats reason why I think that Wireshark developers just feel MUCH more
146 >> comfortable with GPL and thats reason why they just ignoring it.
150 >>> In my understanding there is no legal problem in putting 3-clause BSD
151 >>> code into GPL code. Acutally wireshark includes some 3-clause BSD
155 >> Actually there is really not. BSD to GPL works without problem, but
156 >> many people just don't know it...
158 > ...it is too bad. I strongly believe FOSS developers should know the
159 > intent behind of the both licenses.
161 >>> epan/dissectors/packet-radiotap-defs.h:
163 >>> * Copyright (c) 2003, 2004 David Young. All rights reserved.
167 >>> * Redistribution and use in source and binary forms, with or without
168 >>> * modification, are permitted provided that the following conditions
170 >>> * 1. Redistributions of source code must retain the above copyright
171 >>> * notice, this list of conditions and the following disclaimer.
172 >>> * 2. Redistributions in binary form must reproduce the above copyright
173 >>> * notice, this list of conditions and the following disclaimer in the
174 >>> * documentation and/or other materials provided with the distribution.
175 >>> * 3. The name of David Young may not be used to endorse or promote
176 >>> * products derived from this software without specific prior
177 >>> * written permission.
179 >>> * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
180 >>> * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
181 >>> * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
182 >>> * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
183 >>> * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
184 >>> * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
185 >>> * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
186 >>> * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
187 >>> * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
188 >>> * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
189 >>> * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
190 >>> * OF SUCH DAMAGE.
192 >>> I'd like to separate the legal issue and preference. I think I
193 >>> understand the importance of preference of upstream
194 >>> developers. However, I'd like to clear the legal issue first.
197 >> Legally it's ok. But as you said, developers preference are
198 >> different. And because you are trying to change THEIR code it's
199 >> sometimes better to play they rules.
203 >>> I can image there are people who prefer to GPL as the license covering
204 >>> their software. But here I've taken some corosync code in my
205 >>> dissector. It is essential part of my dissector. And corosync is
207 >> ^^^ This may be problem. Question is how big is that part and if it
208 >> can be possible to make exception there. Can you point that code?
210 >> Steve, we were able to relicense HUGE portion of code in case of
211 >> libqb, are we able to make the same for Wireshark dissector?
213 > Could you see https://github.com/masatake/wireshark-plugin-rhcs/blob/master/src/packet-corosync-totemnet.c#L156
214 > I refer totemnet.c to write dissect_corosynec_totemnet_with_decryption() function.
216 >>> licensed in 3-clause BSD, as you know. I'd like to change the license
217 >>> to merge my code to upstream project. I cannot do it in this context.
218 >>> See https://gitlab.com/wireshark/wireshark/-/issues/3232#c13
228 Red Hat is the author of the totemnet file and can provide that code
229 under GPL if you like. We cannot modify the license for libtomcrypt as
230 we are not the authors. Feel free to change the license for that
231 particular code you rewrote in the link
234 https://github.com/masatake/wireshark-plugin-rhcs/blob/master/src/packet-corosync-totemnet.c#L156
236 under a GPL license if it helps move things along.
243 dissect_corosynec_totemnet_with_decryption(tvbuff_t
*tvb
,
244 packet_info
*pinfo
, proto_tree
*parent_tree
,
245 bool check_crypt_type
,
246 const char* key_for_trial
)
248 unsigned char keys
[48];
249 sober128_prng keygen_prng_state
;
250 sober128_prng stream_prng_state
;
251 unsigned char *hmac_key
= &keys
[32];
252 unsigned char *cipher_key
= &keys
[16];
253 unsigned char *initial_vector
= &keys
[0];
254 unsigned char digest_comparison
[HASH_SHA1_LENGTH
];
259 #define PRIVATE_KEY_LEN_MAX 256
260 char private_key
[PRIVATE_KEY_LEN_MAX
];
261 size_t private_key_len
;
262 unsigned char* hash_digest
;
265 io_len
= tvb_reported_length(tvb
) - (check_crypt_type
? 1: 0);
266 if (io_len
< HASH_SHA1_LENGTH
+ SALT_SIZE
) {
270 io_base
= (uint8_t *)tvb_memdup(pinfo
->pool
, tvb
, 0, io_len
+ (check_crypt_type
? 1: 0));
271 if (check_crypt_type
&&
272 ( io_base
[io_len
] != TOTEM_CRYPTO_SOBER
)) {
276 hash_digest
= io_base
;
277 salt
= io_base
+ HASH_SHA1_LENGTH
;
280 memset(private_key
, 0, sizeof(private_key
));
282 private_key_len
= (strlen(key_for_trial
)+4) & 0xFC;
283 (void) g_strlcpy(private_key
, key_for_trial
, private_key_len
);
286 * Generate MAC, CIPHER, IV keys from private key
288 memset(keys
, 0, sizeof(keys
));
289 sober128_start(&keygen_prng_state
);
290 sober128_add_entropy(private_key
,
291 (unsigned long)private_key_len
, &keygen_prng_state
);
292 sober128_add_entropy(salt
, SALT_SIZE
, &keygen_prng_state
);
293 sober128_read(keys
, sizeof (keys
), &keygen_prng_state
);
296 * Setup stream cipher
298 sober128_start (&stream_prng_state
);
299 sober128_add_entropy (cipher_key
, 16, &stream_prng_state
);
300 sober128_add_entropy (initial_vector
, 16, &stream_prng_state
);
303 * Authenticate contents of message
305 if (ws_hmac_buffer(GCRY_MD_SHA1
, digest_comparison
, io_base
+ HASH_SHA1_LENGTH
, io_len
- HASH_SHA1_LENGTH
, hmac_key
, 16)) {
309 if (memcmp (digest_comparison
, hash_digest
, HASH_SHA1_LENGTH
) != 0)
313 * Decrypt the contents of the message with the cipher key
316 sober128_read(io_base
+ HASH_SHA1_LENGTH
+ SALT_SIZE
,
317 io_len
- (HASH_SHA1_LENGTH
+ SALT_SIZE
),
322 * Dissect the decrypted data
325 tvbuff_t
*decrypted_tvb
;
329 decrypted_tvb
= tvb_new_real_data(io_base
, io_len
, io_len
);
331 tvb_set_child_real_data_tvbuff(tvb
, decrypted_tvb
);
332 add_new_data_source(pinfo
, decrypted_tvb
, "Decrypted Data");
335 dissect_corosync_totemnet_security_header(decrypted_tvb
, pinfo
, parent_tree
,
336 check_crypt_type
, key_for_trial
);
338 next_tvb
= tvb_new_subset_length(decrypted_tvb
,
339 HASH_SHA1_LENGTH
+ SALT_SIZE
,
340 io_len
- (HASH_SHA1_LENGTH
+ SALT_SIZE
));
342 return call_dissector(corosync_totemsrp_handle
, next_tvb
, pinfo
, parent_tree
) + HASH_SHA1_LENGTH
+ SALT_SIZE
;
347 dissect_corosynec_totemnet(tvbuff_t
*tvb
,
348 packet_info
*pinfo
, proto_tree
*parent_tree
,
351 if (corosync_totemnet_private_keys_list
)
353 static int last_key_index
= -1;
356 static int last_check_crypt_type_index
;
357 int check_crypt_type_index
= -1;
358 bool check_crypt_type_list
[] = {false, true};
361 if (last_key_index
!= -1)
365 r
= dissect_corosynec_totemnet_with_decryption(tvb
,
368 check_crypt_type_list
[last_check_crypt_type_index
],
369 corosync_totemnet_private_keys_list
[last_key_index
]);
377 corosync_totemnet_private_keys_list
[key_index
];
380 for (check_crypt_type_index
= 0;
381 check_crypt_type_index
< 2;
382 check_crypt_type_index
++)
386 r
= dissect_corosynec_totemnet_with_decryption(tvb
,
389 check_crypt_type_list
[check_crypt_type_index
],
390 corosync_totemnet_private_keys_list
[key_index
]);
393 last_key_index
= key_index
;
394 last_check_crypt_type_index
= check_crypt_type_index
;
405 return call_dissector(corosync_totemsrp_handle
, tvb
, pinfo
, parent_tree
);
409 corosync_totemnet_shutdown(void)
411 g_strfreev(corosync_totemnet_private_keys_list
);
415 proto_register_corosync_totemnet(void)
417 module_t
*corosync_totemnet_module
;
419 static hf_register_info hf
[] = {
420 { &hf_corosync_totemnet_security_header_hash_digest
,
421 { "Hash digest", "corosync_totemnet.security_header_hash_digest",
422 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
424 { &hf_corosync_totemnet_security_header_salt
,
425 { "Salt", "corosync_totemnet.security_header_salt",
426 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
428 { &hf_corosync_totemnet_security_crypto_type
,
429 { "Cryptographic Type", "corosync_totemnet.security_crypto_type",
430 FT_UINT8
, BASE_DEC
, VALS(corosync_totemnet_crypto_type
), 0x0,
432 { &hf_corosync_totemnet_security_crypto_key
,
433 { "Private Key for decryption", "corosync_totemnet.security_crypto_key",
434 FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
437 static int *ett_corosync_totemnet
[] = {
438 &ett_corosync_totemnet_security_header
,
441 proto_corosync_totemnet
= proto_register_protocol("Totemnet Layer of Corosync Cluster Engine",
442 "COROSYNC/TOTEMNET", "corosync_totemnet");
443 proto_register_field_array(proto_corosync_totemnet
, hf
, array_length(hf
));
444 proto_register_subtree_array(ett_corosync_totemnet
, array_length(ett_corosync_totemnet
));
446 corosync_totemnet_module
= prefs_register_protocol(proto_corosync_totemnet
,
447 proto_reg_handoff_corosync_totemnet
);
449 prefs_register_string_preference(corosync_totemnet_module
, "private_keys", "Private keys",
450 "Semicolon-separated list of keys for decryption(e.g. key1;key2;..." ,
451 (const char **)&corosync_totemnet_private_keys
);
453 register_shutdown_routine(corosync_totemnet_shutdown
);
455 corosync_totemnet_handle
= register_dissector("corosync_totemnet", dissect_corosynec_totemnet
, proto_corosync_totemnet
);
459 proto_reg_handoff_corosync_totemnet(void)
461 static bool initialized
= false;
465 corosync_totemsrp_handle
= find_dissector_add_dependency("corosync_totemsrp", proto_corosync_totemnet
);
467 dissector_add_uint_range_with_preference("udp.port", PORT_COROSYNC_TOTEMNET_RANGE
, corosync_totemnet_handle
);
471 g_strfreev(corosync_totemnet_private_keys_list
);
472 corosync_totemnet_private_keys_list
= g_strsplit(corosync_totemnet_private_keys
, ";", 0);
476 * Editor modelines - https://www.wireshark.org/tools/modelines.html
481 * indent-tabs-mode: nil
484 * vi: set shiftwidth=4 tabstop=8 expandtab:
485 * :indentSize=4:tabSize=8:noTabs=true: