Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-ssh.c
blob5a36ebd2e5fe61c1527f2c4ed77c8511b0e20028
1 /* packet-ssh.c
2 * Routines for ssh packet dissection
4 * Huagang XIE <huagang@intruvert.com>
5 * Kees Cook <kees@outflux.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-mysql.c
13 * SPDX-License-Identifier: GPL-2.0-or-later
16 * Note: support SSH v1 and v2 now.
20 /* SSH version 2 is defined in:
22 * RFC 4250: The Secure Shell (SSH) Protocol Assigned Numbers
23 * RFC 4251: The Secure Shell (SSH) Protocol Architecture
24 * RFC 4252: The Secure Shell (SSH) Authentication Protocol
25 * RFC 4253: The Secure Shell (SSH) Transport Layer Protocol
26 * RFC 4254: The Secure Shell (SSH) Connection Protocol
28 * SSH versions under 2 were never officially standardized.
30 * Diffie-Hellman Group Exchange is defined in:
32 * RFC 4419: Diffie-Hellman Group Exchange for
33 * the Secure Shell (SSH) Transport Layer Protocol
36 /* "SSH" prefixes are for version 2, whereas "SSH1" is for version 1 */
38 #include "config.h"
39 /* Start with WIRESHARK_LOG_DOMAINS=packet-ssh and WIRESHARK_LOG_LEVEL=debug to see messages. */
40 #define WS_LOG_DOMAIN "packet-ssh"
42 // Define this to get hex dumps more similar to what you get in openssh. If not defined, dumps look more like what you get with other dissectors.
43 #define OPENSSH_STYLE
45 #include <errno.h>
47 #include <epan/packet.h>
48 #include <epan/exceptions.h>
49 #include <epan/sctpppids.h>
50 #include <epan/prefs.h>
51 #include <epan/expert.h>
52 #include <epan/proto_data.h>
53 #include <wsutil/strtoi.h>
54 #include <wsutil/to_str.h>
55 #include <wsutil/file_util.h>
56 #include <wsutil/filesystem.h>
57 #include <wsutil/wsgcrypt.h>
58 #include <wsutil/curve25519.h>
59 #include <wsutil/pint.h>
60 #include <wsutil/str_util.h>
61 #include <wsutil/wslog.h>
62 #include <epan/secrets.h>
63 #include <wiretap/secrets-types.h>
65 #if defined(HAVE_LIBGNUTLS)
66 #include <gnutls/abstract.h>
67 #endif
69 #include "packet-tcp.h"
71 void proto_register_ssh(void);
72 void proto_reg_handoff_ssh(void);
74 /* SSH Version 1 definition , from openssh ssh1.h */
75 #define SSH1_MSG_NONE 0 /* no message */
76 #define SSH1_MSG_DISCONNECT 1 /* cause (string) */
77 #define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
78 #define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
79 #define SSH1_CMSG_USER 4 /* user (string) */
82 #define SSH_VERSION_UNKNOWN 0
83 #define SSH_VERSION_1 1
84 #define SSH_VERSION_2 2
86 /* proto data */
88 typedef struct {
89 uint8_t *data;
90 unsigned length;
91 } ssh_bignum;
93 #define SSH_KEX_CURVE25519 0x00010000
94 #define SSH_KEX_DH_GEX 0x00020000
95 #define SSH_KEX_DH_GROUP1 0x00030001
96 #define SSH_KEX_DH_GROUP14 0x00030014
97 #define SSH_KEX_DH_GROUP16 0x00030016
98 #define SSH_KEX_DH_GROUP18 0x00030018
100 #define SSH_KEX_HASH_SHA1 1
101 #define SSH_KEX_HASH_SHA256 2
102 #define SSH_KEX_HASH_SHA512 4
104 #define DIGEST_MAX_SIZE 48
106 typedef struct _ssh_message_info_t {
107 uint32_t sequence_number;
108 unsigned char *plain_data; /**< Decrypted data. */
109 unsigned data_len; /**< Length of decrypted data. */
110 int id; /**< Identifies the exact message within a frame
111 (there can be multiple records in a frame). */
112 uint32_t byte_seq;
113 uint32_t next_byte_seq;
114 struct _ssh_message_info_t* next;
115 uint8_t calc_mac[DIGEST_MAX_SIZE];
116 } ssh_message_info_t;
118 typedef struct {
119 bool from_server;
120 ssh_message_info_t * messages;
121 } ssh_packet_info_t;
123 typedef struct _ssh_channel_info_t {
124 uint32_t byte_seq;
125 uint16_t flags;
126 wmem_tree_t *multisegment_pdus;
127 dissector_handle_t handle;
128 } ssh_channel_info_t;
130 struct ssh_peer_data {
131 unsigned counter;
133 uint32_t frame_version_start;
134 uint32_t frame_version_end;
136 uint32_t frame_key_start;
137 uint32_t frame_key_end;
138 int frame_key_end_offset;
140 char* kex_proposal;
142 /* For all subsequent proposals,
143 [0] is client-to-server and [1] is server-to-client. */
144 #define CLIENT_TO_SERVER_PROPOSAL 0
145 #define SERVER_TO_CLIENT_PROPOSAL 1
147 char* mac_proposals[2];
148 char* mac;
149 int mac_length;
151 char* enc_proposals[2];
152 char* enc;
154 char* comp_proposals[2];
155 char* comp;
157 int length_is_plaintext;
159 // see libgcrypt source, gcrypt.h:gcry_cipher_algos
160 unsigned cipher_id;
161 unsigned mac_id;
162 // chacha20 needs two cipher handles
163 gcry_cipher_hd_t cipher, cipher_2;
164 unsigned sequence_number;
165 uint32_t seq_num_kex_init;
166 // union ??? -- begin
167 uint32_t seq_num_gex_req;
168 uint32_t seq_num_gex_grp;
169 uint32_t seq_num_gex_ini;
170 uint32_t seq_num_gex_rep;
171 // --
172 uint32_t seq_num_ecdh_ini;
173 uint32_t seq_num_ecdh_rep;
174 // --
175 uint32_t seq_num_dh_ini;
176 uint32_t seq_num_dh_rep;
177 // union ??? -- end
178 uint32_t seq_num_new_key;
179 ssh_bignum *bn_cookie;
180 uint8_t iv[12];
181 uint8_t hmac_iv[DIGEST_MAX_SIZE];
182 unsigned hmac_iv_len;
184 wmem_map_t *channel_info; /**< Map of sender channel numbers to recipient numbers. */
185 wmem_map_t *channel_handles; /**< Map of recipient channel numbers to subdissector handles. */
186 struct ssh_flow_data * global_data;
189 struct ssh_flow_data {
190 unsigned version;
192 char* kex;
193 int (*kex_specific_dissector)(uint8_t msg_code, tvbuff_t *tvb,
194 packet_info *pinfo, int offset, proto_tree *tree,
195 struct ssh_flow_data *global_data, unsigned *seq_num);
197 /* [0] is client's, [1] is server's */
198 #define CLIENT_PEER_DATA 0
199 #define SERVER_PEER_DATA 1
200 struct ssh_peer_data peer_data[2];
202 char *session_id;
203 unsigned session_id_length;
204 ssh_bignum *kex_e;
205 ssh_bignum *kex_f;
206 ssh_bignum *kex_gex_p; // Group modulo
207 ssh_bignum *kex_gex_g; // Group generator
208 ssh_bignum *secret;
209 wmem_array_t *kex_client_version;
210 wmem_array_t *kex_server_version;
211 wmem_array_t *kex_client_key_exchange_init;
212 wmem_array_t *kex_server_key_exchange_init;
213 wmem_array_t *kex_server_host_key_blob;
214 wmem_array_t *kex_gex_bits_min;
215 wmem_array_t *kex_gex_bits_req;
216 wmem_array_t *kex_gex_bits_max;
217 wmem_array_t *kex_shared_secret;
218 bool do_decrypt;
219 bool ext_ping_openssh_offered;
220 ssh_bignum new_keys[6];
223 typedef struct {
224 char *type;
225 ssh_bignum *key_material;
226 } ssh_key_map_entry_t;
228 static GHashTable * ssh_master_key_map;
230 static int proto_ssh;
232 /* Version exchange */
233 static int hf_ssh_protocol;
235 /* Framing */
236 static int hf_ssh_packet_length;
237 static int hf_ssh_packet_length_encrypted;
238 static int hf_ssh_padding_length;
239 static int hf_ssh_payload;
240 static int hf_ssh_encrypted_packet;
241 static int hf_ssh_padding_string;
242 static int hf_ssh_mac_string;
243 static int hf_ssh_mac_status;
244 static int hf_ssh_seq_num;
245 static int hf_ssh_direction;
247 /* Message codes */
248 static int hf_ssh_msg_code;
249 static int hf_ssh2_msg_code;
250 static int hf_ssh2_kex_dh_msg_code;
251 static int hf_ssh2_kex_dh_gex_msg_code;
252 static int hf_ssh2_kex_ecdh_msg_code;
253 static int hf_ssh2_ext_ping_msg_code;
255 /* Algorithm negotiation */
256 static int hf_ssh_cookie;
257 static int hf_ssh_kex_algorithms;
258 static int hf_ssh_server_host_key_algorithms;
259 static int hf_ssh_encryption_algorithms_client_to_server;
260 static int hf_ssh_encryption_algorithms_server_to_client;
261 static int hf_ssh_mac_algorithms_client_to_server;
262 static int hf_ssh_mac_algorithms_server_to_client;
263 static int hf_ssh_compression_algorithms_client_to_server;
264 static int hf_ssh_compression_algorithms_server_to_client;
265 static int hf_ssh_languages_client_to_server;
266 static int hf_ssh_languages_server_to_client;
267 static int hf_ssh_kex_algorithms_length;
268 static int hf_ssh_server_host_key_algorithms_length;
269 static int hf_ssh_encryption_algorithms_client_to_server_length;
270 static int hf_ssh_encryption_algorithms_server_to_client_length;
271 static int hf_ssh_mac_algorithms_client_to_server_length;
272 static int hf_ssh_mac_algorithms_server_to_client_length;
273 static int hf_ssh_compression_algorithms_client_to_server_length;
274 static int hf_ssh_compression_algorithms_server_to_client_length;
275 static int hf_ssh_languages_client_to_server_length;
276 static int hf_ssh_languages_server_to_client_length;
277 static int hf_ssh_first_kex_packet_follows;
278 static int hf_ssh_kex_reserved;
279 static int hf_ssh_kex_hassh_algo;
280 static int hf_ssh_kex_hassh;
281 static int hf_ssh_kex_hasshserver_algo;
282 static int hf_ssh_kex_hasshserver;
284 /* Key exchange common elements */
285 static int hf_ssh_hostkey_length;
286 static int hf_ssh_hostkey_type_length;
287 static int hf_ssh_hostkey_type;
288 static int hf_ssh_hostkey_data;
289 static int hf_ssh_hostkey_rsa_n;
290 static int hf_ssh_hostkey_rsa_e;
291 static int hf_ssh_hostkey_dsa_p;
292 static int hf_ssh_hostkey_dsa_q;
293 static int hf_ssh_hostkey_dsa_g;
294 static int hf_ssh_hostkey_dsa_y;
295 static int hf_ssh_hostkey_ecdsa_curve_id;
296 static int hf_ssh_hostkey_ecdsa_curve_id_length;
297 static int hf_ssh_hostkey_ecdsa_q;
298 static int hf_ssh_hostkey_ecdsa_q_length;
299 static int hf_ssh_hostkey_eddsa_key;
300 static int hf_ssh_hostkey_eddsa_key_length;
301 static int hf_ssh_hostsig_length;
302 static int hf_ssh_hostsig_type_length;
303 static int hf_ssh_hostsig_type;
304 static int hf_ssh_hostsig_rsa;
305 static int hf_ssh_hostsig_dsa;
306 static int hf_ssh_hostsig_data;
308 /* Key exchange: Diffie-Hellman */
309 static int hf_ssh_dh_e;
310 static int hf_ssh_dh_f;
312 /* Key exchange: Diffie-Hellman Group Exchange */
313 static int hf_ssh_dh_gex_min;
314 static int hf_ssh_dh_gex_nbits;
315 static int hf_ssh_dh_gex_max;
316 static int hf_ssh_dh_gex_p;
317 static int hf_ssh_dh_gex_g;
319 /* Key exchange: Elliptic Curve Diffie-Hellman */
320 static int hf_ssh_ecdh_q_c;
321 static int hf_ssh_ecdh_q_c_length;
322 static int hf_ssh_ecdh_q_s;
323 static int hf_ssh_ecdh_q_s_length;
325 /* Extension negotiation */
326 static int hf_ssh_ext_count;
327 static int hf_ssh_ext_name_length;
328 static int hf_ssh_ext_name;
329 static int hf_ssh_ext_value_length;
330 static int hf_ssh_ext_value;
331 static int hf_ssh_ext_server_sig_algs_algorithms;
332 static int hf_ssh_ext_delay_compression_algorithms_client_to_server_length;
333 static int hf_ssh_ext_delay_compression_algorithms_client_to_server;
334 static int hf_ssh_ext_delay_compression_algorithms_server_to_client_length;
335 static int hf_ssh_ext_delay_compression_algorithms_server_to_client;
336 static int hf_ssh_ext_no_flow_control_value;
337 static int hf_ssh_ext_elevation_value;
338 static int hf_ssh_ext_prop_publickey_algorithms_algorithms;
340 /* Miscellaneous */
341 static int hf_ssh_mpint_length;
343 static int hf_ssh_ignore_data_length;
344 static int hf_ssh_ignore_data;
345 static int hf_ssh_debug_always_display;
346 static int hf_ssh_debug_message_length;
347 static int hf_ssh_debug_message;
348 static int hf_ssh_service_name_length;
349 static int hf_ssh_service_name;
350 static int hf_ssh_userauth_user_name_length;
351 static int hf_ssh_userauth_user_name;
352 static int hf_ssh_userauth_change_password;
353 static int hf_ssh_userauth_service_name_length;
354 static int hf_ssh_userauth_service_name;
355 static int hf_ssh_userauth_method_name_length;
356 static int hf_ssh_userauth_method_name;
357 static int hf_ssh_userauth_have_signature;
358 static int hf_ssh_userauth_password_length;
359 static int hf_ssh_userauth_password;
360 static int hf_ssh_userauth_new_password_length;
361 static int hf_ssh_userauth_new_password;
362 static int hf_ssh_auth_failure_list_length;
363 static int hf_ssh_auth_failure_list;
364 static int hf_ssh_userauth_partial_success;
365 static int hf_ssh_userauth_pka_name_len;
366 static int hf_ssh_userauth_pka_name;
367 static int hf_ssh_pk_blob_name_length;
368 static int hf_ssh_pk_blob_name;
369 static int hf_ssh_blob_length;
370 static int hf_ssh_signature_length;
371 static int hf_ssh_pk_sig_blob_name_length;
372 static int hf_ssh_pk_sig_blob_name;
373 static int hf_ssh_connection_type_name_len;
374 static int hf_ssh_connection_type_name;
375 static int hf_ssh_connection_sender_channel;
376 static int hf_ssh_connection_recipient_channel;
377 static int hf_ssh_connection_initial_window;
378 static int hf_ssh_connection_maximum_packet_size;
379 static int hf_ssh_global_request_name_len;
380 static int hf_ssh_global_request_name;
381 static int hf_ssh_global_request_want_reply;
382 static int hf_ssh_global_request_hostkeys_array_len;
383 static int hf_ssh_channel_request_name_len;
384 static int hf_ssh_channel_request_name;
385 static int hf_ssh_channel_request_want_reply;
386 static int hf_ssh_subsystem_name_len;
387 static int hf_ssh_subsystem_name;
388 static int hf_ssh_channel_window_adjust;
389 static int hf_ssh_channel_data_len;
390 static int hf_ssh_exit_status;
391 static int hf_ssh_disconnect_reason;
392 static int hf_ssh_disconnect_description_length;
393 static int hf_ssh_disconnect_description;
394 static int hf_ssh_lang_tag_length;
395 static int hf_ssh_lang_tag;
396 static int hf_ssh_ping_data_length;
397 static int hf_ssh_ping_data;
398 static int hf_ssh_pong_data_length;
399 static int hf_ssh_pong_data;
401 static int hf_ssh_blob_p;
402 static int hf_ssh_blob_e;
404 static int hf_ssh_pk_sig_s_length;
405 static int hf_ssh_pk_sig_s;
407 static int hf_ssh_reassembled_in;
408 static int hf_ssh_reassembled_length;
409 static int hf_ssh_reassembled_data;
410 static int hf_ssh_segments;
411 static int hf_ssh_segment;
412 static int hf_ssh_segment_overlap;
413 static int hf_ssh_segment_overlap_conflict;
414 static int hf_ssh_segment_multiple_tails;
415 static int hf_ssh_segment_too_long_fragment;
416 static int hf_ssh_segment_error;
417 static int hf_ssh_segment_count;
418 static int hf_ssh_segment_data;
420 static int ett_ssh;
421 static int ett_key_exchange;
422 static int ett_key_exchange_host_key;
423 static int ett_key_exchange_host_sig;
424 static int ett_extension;
425 static int ett_userauth_pk_blob;
426 static int ett_userauth_pk_signautre;
427 static int ett_key_init;
428 static int ett_ssh1;
429 static int ett_ssh2;
430 static int ett_ssh_segments;
431 static int ett_ssh_segment;
433 static expert_field ei_ssh_packet_length;
434 static expert_field ei_ssh_packet_decode;
435 static expert_field ei_ssh_channel_number;
436 static expert_field ei_ssh_invalid_keylen;
437 static expert_field ei_ssh_mac_bad;
439 static bool ssh_desegment = true;
441 static dissector_handle_t ssh_handle;
442 static dissector_handle_t sftp_handle;
444 static const char *pref_keylog_file;
445 static FILE *ssh_keylog_file;
447 static reassembly_table ssh_reassembly_table;
449 static const fragment_items ssh_segment_items = {
450 &ett_ssh_segment,
451 &ett_ssh_segments,
452 &hf_ssh_segments,
453 &hf_ssh_segment,
454 &hf_ssh_segment_overlap,
455 &hf_ssh_segment_overlap_conflict,
456 &hf_ssh_segment_multiple_tails,
457 &hf_ssh_segment_too_long_fragment,
458 &hf_ssh_segment_error,
459 &hf_ssh_segment_count,
460 &hf_ssh_reassembled_in,
461 &hf_ssh_reassembled_length,
462 &hf_ssh_reassembled_data,
463 "Segments"
466 #define SSH_DECRYPT_DEBUG
468 #ifdef SSH_DECRYPT_DEBUG
469 static const char *ssh_debug_file_name;
470 #endif
472 #define TCP_RANGE_SSH "22"
473 #define SCTP_PORT_SSH 22
475 /* Message Numbers (from RFC 4250) (1-255) */
477 /* Transport layer protocol: generic (1-19) */
478 #define SSH_MSG_DISCONNECT 1
479 #define SSH_MSG_IGNORE 2
480 #define SSH_MSG_UNIMPLEMENTED 3
481 #define SSH_MSG_DEBUG 4
482 #define SSH_MSG_SERVICE_REQUEST 5
483 #define SSH_MSG_SERVICE_ACCEPT 6
484 #define SSH_MSG_EXT_INFO 7
485 #define SSH_MSG_NEWCOMPRESS 8
487 /* Transport layer protocol: Algorithm negotiation (20-29) */
488 #define SSH_MSG_KEXINIT 20
489 #define SSH_MSG_NEWKEYS 21
491 /* Transport layer: Key exchange method specific (reusable) (30-49) */
492 #define SSH_MSG_KEXDH_INIT 30
493 #define SSH_MSG_KEXDH_REPLY 31
495 #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
496 #define SSH_MSG_KEX_DH_GEX_GROUP 31
497 #define SSH_MSG_KEX_DH_GEX_INIT 32
498 #define SSH_MSG_KEX_DH_GEX_REPLY 33
499 #define SSH_MSG_KEX_DH_GEX_REQUEST 34
501 #define SSH_MSG_KEX_ECDH_INIT 30
502 #define SSH_MSG_KEX_ECDH_REPLY 31
504 /* User authentication protocol: generic (50-59) */
505 #define SSH_MSG_USERAUTH_REQUEST 50
506 #define SSH_MSG_USERAUTH_FAILURE 51
507 #define SSH_MSG_USERAUTH_SUCCESS 52
508 #define SSH_MSG_USERAUTH_BANNER 53
510 /* User authentication protocol: method specific (reusable) (50-79) */
511 #define SSH_MSG_USERAUTH_PK_OK 60
513 /* Connection protocol: generic (80-89) */
514 #define SSH_MSG_GLOBAL_REQUEST 80
515 #define SSH_MSG_REQUEST_SUCCESS 81
516 #define SSH_MSG_REQUEST_FAILURE 82
518 /* Connection protocol: channel related messages (90-127) */
519 #define SSH_MSG_CHANNEL_OPEN 90
520 #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
521 #define SSH_MSG_CHANNEL_OPEN_FAILURE 92
522 #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
523 #define SSH_MSG_CHANNEL_DATA 94
524 #define SSH_MSG_CHANNEL_EXTENDED_DATA 95
525 #define SSH_MSG_CHANNEL_EOF 96
526 #define SSH_MSG_CHANNEL_CLOSE 97
527 #define SSH_MSG_CHANNEL_REQUEST 98
528 #define SSH_MSG_CHANNEL_SUCCESS 99
529 #define SSH_MSG_CHANNEL_FAILURE 100
531 /* 128-191 reserved for client protocols */
532 /* 192-255 local extensions */
533 #define SSH_MSG_PING 192
534 #define SSH_MSG_PONG 193
536 #define CIPHER_AES128_CTR 0x00010001
537 #define CIPHER_AES192_CTR 0x00010003
538 #define CIPHER_AES256_CTR 0x00010004
539 #define CIPHER_AES128_CBC 0x00020001
540 #define CIPHER_AES192_CBC 0x00020002
541 #define CIPHER_AES256_CBC 0x00020004
542 #define CIPHER_AES128_GCM 0x00040001
543 //#define CIPHER_AES192_GCM 0x00040002 -- does not exist
544 #define CIPHER_AES256_GCM 0x00040004
546 #define CIPHER_MAC_SHA2_256 0x00020001
548 static const value_string ssh_direction_vals[] = {
549 { CLIENT_TO_SERVER_PROPOSAL, "client-to-server" },
550 { SERVER_TO_CLIENT_PROPOSAL, "server-to-client" },
551 { 0, NULL }
554 static const value_string ssh2_msg_vals[] = {
555 { SSH_MSG_DISCONNECT, "Disconnect" },
556 { SSH_MSG_IGNORE, "Ignore" },
557 { SSH_MSG_UNIMPLEMENTED, "Unimplemented" },
558 { SSH_MSG_DEBUG, "Debug" },
559 { SSH_MSG_SERVICE_REQUEST, "Service Request" },
560 { SSH_MSG_SERVICE_ACCEPT, "Service Accept" },
561 { SSH_MSG_EXT_INFO, "Extension Information" },
562 { SSH_MSG_NEWCOMPRESS, "New Compression" },
563 { SSH_MSG_KEXINIT, "Key Exchange Init" },
564 { SSH_MSG_NEWKEYS, "New Keys" },
565 { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" },
566 { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" },
567 { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" },
568 { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" },
569 { SSH_MSG_GLOBAL_REQUEST, "Global Request" },
570 { SSH_MSG_REQUEST_SUCCESS, "Request Success" },
571 { SSH_MSG_REQUEST_FAILURE, "Request Failure" },
572 { SSH_MSG_CHANNEL_OPEN, "Channel Open" },
573 { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
574 { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" },
575 { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" },
576 { SSH_MSG_CHANNEL_DATA, "Channel Data" },
577 { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" },
578 { SSH_MSG_CHANNEL_EOF, "Channel EOF" },
579 { SSH_MSG_CHANNEL_CLOSE, "Channel Close" },
580 { SSH_MSG_CHANNEL_REQUEST, "Channel Request" },
581 { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" },
582 { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" },
583 { SSH_MSG_USERAUTH_PK_OK, "Public Key algorithm accepted" },
584 { 0, NULL }
587 static const value_string ssh2_kex_dh_msg_vals[] = {
588 { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" },
589 { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" },
590 { 0, NULL }
593 static const value_string ssh2_kex_dh_gex_msg_vals[] = {
594 { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" },
595 { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" },
596 { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" },
597 { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" },
598 { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" },
599 { 0, NULL }
602 static const value_string ssh2_kex_ecdh_msg_vals[] = {
603 { SSH_MSG_KEX_ECDH_INIT, "Elliptic Curve Diffie-Hellman Key Exchange Init" },
604 { SSH_MSG_KEX_ECDH_REPLY, "Elliptic Curve Diffie-Hellman Key Exchange Reply" },
605 { 0, NULL }
608 static const value_string ssh2_ext_ping_msg_vals[] = {
609 { SSH_MSG_PING, "Ping" },
610 { SSH_MSG_PONG, "Pong" },
611 { 0, NULL }
614 static const value_string ssh1_msg_vals[] = {
615 {SSH1_MSG_NONE, "No Message"},
616 {SSH1_MSG_DISCONNECT, "Disconnect"},
617 {SSH1_SMSG_PUBLIC_KEY, "Public Key"},
618 {SSH1_CMSG_SESSION_KEY, "Session Key"},
619 {SSH1_CMSG_USER, "User"},
620 {0, NULL}
623 static int ssh_dissect_key_init(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree,
624 int is_response,
625 struct ssh_flow_data *global_data);
626 static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
627 int hf_index_length, int hf_index_value, char **store);
628 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
629 struct ssh_flow_data *global_data,
630 int offset, proto_tree *tree, int is_response,
631 bool *need_desegmentation);
632 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
633 struct ssh_flow_data *global_data,
634 int offset, proto_tree *tree, int is_response,
635 bool *need_desegmentation);
636 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
637 struct ssh_flow_data *global_data,
638 int offset, proto_tree *tree, int is_response,
639 bool *need_desegmentation);
640 static int ssh_dissect_kex_dh(uint8_t msg_code, tvbuff_t *tvb,
641 packet_info *pinfo, int offset, proto_tree *tree,
642 struct ssh_flow_data *global_data, unsigned *seq_num);
643 static int ssh_dissect_kex_dh_gex(uint8_t msg_code, tvbuff_t *tvb,
644 packet_info *pinfo, int offset, proto_tree *tree,
645 struct ssh_flow_data *global_data, unsigned *seq_num);
646 static int ssh_dissect_kex_ecdh(uint8_t msg_code, tvbuff_t *tvb,
647 packet_info *pinfo, int offset, proto_tree *tree,
648 struct ssh_flow_data *global_data, unsigned *seq_num);
649 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
650 struct ssh_flow_data *global_data,
651 int offset, proto_tree *tree, int is_response, unsigned *version,
652 bool *need_desegmentation);
653 static int ssh_try_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
654 struct ssh_peer_data *peer_data, int offset, proto_tree *tree);
655 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
656 struct ssh_peer_data *peer_data,
657 int offset, proto_tree *tree);
658 static void ssh_choose_algo(char *client, char *server, char **result);
659 static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
660 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
662 static void ssh_keylog_read_file(void);
663 static void ssh_keylog_process_line(const char *line);
664 static void ssh_keylog_process_lines(const uint8_t *data, unsigned datalen);
665 static void ssh_keylog_reset(void);
666 static ssh_bignum *ssh_kex_make_bignum(const uint8_t *data, unsigned length);
667 static bool ssh_read_e(tvbuff_t *tvb, int offset,
668 struct ssh_flow_data *global_data);
669 static bool ssh_read_f(tvbuff_t *tvb, int offset,
670 struct ssh_flow_data *global_data);
671 static ssh_bignum * ssh_read_mpint(tvbuff_t *tvb, int offset);
672 static void ssh_keylog_hash_write_secret(struct ssh_flow_data *global_data);
673 static ssh_bignum *ssh_kex_shared_secret(int kex_type, ssh_bignum *pub, ssh_bignum *priv, ssh_bignum *modulo);
674 static void ssh_hash_buffer_put_string(wmem_array_t *buffer, const char *string,
675 unsigned len);
676 static void ssh_hash_buffer_put_uint32(wmem_array_t *buffer, unsigned val);
677 static char *ssh_string(const char *string, unsigned len);
678 static void ssh_derive_symmetric_keys(ssh_bignum *shared_secret,
679 char *exchange_hash, unsigned hash_length,
680 struct ssh_flow_data *global_data);
681 static void ssh_derive_symmetric_key(ssh_bignum *shared_secret,
682 char *exchange_hash, unsigned hash_length, char id,
683 ssh_bignum *result_key, struct ssh_flow_data *global_data, unsigned we_need);
685 static void ssh_choose_enc_mac(struct ssh_flow_data *global_data);
686 static void ssh_decryption_set_cipher_id(struct ssh_peer_data *peer);
687 static void ssh_decryption_setup_cipher(struct ssh_peer_data *peer,
688 ssh_bignum *iv, ssh_bignum *key);
689 static void ssh_decryption_set_mac_id(struct ssh_peer_data *peer);
690 static void ssh_decryption_setup_mac(struct ssh_peer_data *peer,
691 ssh_bignum *iv);
692 static void ssh_increment_message_number(packet_info *pinfo,
693 struct ssh_flow_data *global_data, bool is_response);
694 static unsigned ssh_decrypt_packet(tvbuff_t *tvb, packet_info *pinfo,
695 struct ssh_peer_data *peer_data, int offset);
696 static bool ssh_decrypt_chacha20(gcry_cipher_hd_t hd, uint32_t seqnr,
697 uint32_t counter, const unsigned char *ctext, unsigned ctext_len,
698 unsigned char *plain, unsigned plain_len);
699 static proto_item * ssh_tree_add_mac(proto_tree *tree, tvbuff_t *tvb, const unsigned offset, const unsigned mac_len,
700 const int hf_mac, const int hf_mac_status, struct expert_field* bad_checksum_expert,
701 packet_info *pinfo, const uint8_t * calc_mac, const unsigned flags);
703 static int ssh_dissect_decrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
704 struct ssh_peer_data *peer_data, proto_tree *tree,
705 ssh_message_info_t *message);
706 static int ssh_dissect_transport_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
707 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code);
708 static int ssh_dissect_rfc8308_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
709 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree);
710 static int ssh_dissect_userauth_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
711 int offset, proto_item *msg_type_tree, unsigned msg_code);
712 static int ssh_dissect_userauth_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
713 int offset, proto_item *msg_type_tree, unsigned msg_code);
714 static int ssh_dissect_connection_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
715 struct ssh_peer_data *peer_data, int offset, proto_item *msg_type_tree,
716 unsigned msg_code, ssh_message_info_t *message);
717 static int ssh_dissect_connection_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
718 int offset, proto_item *msg_type_tree, unsigned msg_code);
719 static int ssh_dissect_local_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
720 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code);
721 static int ssh_dissect_public_key_blob(tvbuff_t *packet_tvb, packet_info *pinfo,
722 int offset, proto_item *msg_type_tree);
723 static int ssh_dissect_public_key_signature(tvbuff_t *packet_tvb, packet_info *pinfo,
724 int offset, proto_item *msg_type_tree);
726 static void create_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, uint32_t sender_channel);
727 static ssh_channel_info_t* get_channel_info_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel);
728 static void set_subdissector_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, const uint8_t* subsystem_name);
730 #define SSH_DEBUG_USE_STDERR "-"
732 #ifdef SSH_DECRYPT_DEBUG
733 static void
734 ssh_debug_printf(const char* fmt,...) G_GNUC_PRINTF(1,2);
735 static void
736 ssh_print_data(const char* name, const unsigned char* data, size_t len);
737 static void
738 ssh_set_debug(const char* name);
739 static void
740 ssh_debug_flush(void);
741 #else
743 /* No debug: nullify debug operation*/
744 static inline void G_GNUC_PRINTF(1,2)
745 ssh_debug_printf(const char* fmt _U_,...)
748 #define ssh_print_data(a, b, c)
749 #define ssh_print_string(a, b)
750 #define ssh_set_debug(name)
751 #define ssh_debug_flush()
753 #endif /* SSH_DECRYPT_DEBUG */
755 static int
756 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
758 proto_tree *ssh_tree;
759 proto_item *ti;
760 conversation_t *conversation;
761 int last_offset, offset = 0;
763 bool is_response = (pinfo->destport != pinfo->match_uint),
764 need_desegmentation;
765 unsigned version;
767 struct ssh_flow_data *global_data = NULL;
768 struct ssh_peer_data *peer_data;
770 ssh_debug_printf("\ndissect_ssh enter frame #%u (%s)\n", pinfo->num, (pinfo->fd->visited)?"already visited":"first time");
772 conversation = find_or_create_conversation(pinfo);
774 global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
775 if (!global_data) {
776 global_data = wmem_new0(wmem_file_scope(), struct ssh_flow_data);
777 global_data->version = SSH_VERSION_UNKNOWN;
778 global_data->kex_specific_dissector = ssh_dissect_kex_dh;
779 global_data->peer_data[CLIENT_PEER_DATA].mac_length = -1;
780 global_data->peer_data[SERVER_PEER_DATA].mac_length = -1;
781 global_data->peer_data[CLIENT_PEER_DATA].sequence_number = 0;
782 global_data->peer_data[SERVER_PEER_DATA].sequence_number = 0;
783 global_data->peer_data[CLIENT_PEER_DATA].seq_num_kex_init = 0;
784 global_data->peer_data[SERVER_PEER_DATA].seq_num_kex_init = 0;
785 global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_req = 0;
786 global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_req = 0;
787 global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_grp = 0;
788 global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_grp = 0;
789 global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_ini = 0;
790 global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_ini = 0;
791 global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_rep = 0;
792 global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_rep = 0;
793 global_data->peer_data[CLIENT_PEER_DATA].seq_num_ecdh_ini = 0;
794 global_data->peer_data[SERVER_PEER_DATA].seq_num_ecdh_ini = 0;
795 global_data->peer_data[CLIENT_PEER_DATA].seq_num_ecdh_rep = 0;
796 global_data->peer_data[SERVER_PEER_DATA].seq_num_ecdh_rep = 0;
797 global_data->peer_data[CLIENT_PEER_DATA].seq_num_dh_ini = 0;
798 global_data->peer_data[SERVER_PEER_DATA].seq_num_dh_ini = 0;
799 global_data->peer_data[CLIENT_PEER_DATA].seq_num_dh_rep = 0;
800 global_data->peer_data[SERVER_PEER_DATA].seq_num_dh_rep = 0;
801 global_data->peer_data[CLIENT_PEER_DATA].seq_num_new_key = 0;
802 global_data->peer_data[SERVER_PEER_DATA].seq_num_new_key = 0;
803 global_data->peer_data[CLIENT_PEER_DATA].bn_cookie = NULL;
804 global_data->peer_data[SERVER_PEER_DATA].bn_cookie = NULL;
805 global_data->peer_data[CLIENT_PEER_DATA].global_data = global_data;
806 global_data->peer_data[SERVER_PEER_DATA].global_data = global_data;
807 global_data->kex_client_version = wmem_array_new(wmem_file_scope(), 1);
808 global_data->kex_server_version = wmem_array_new(wmem_file_scope(), 1);
809 global_data->kex_client_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
810 global_data->kex_server_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
811 global_data->kex_server_host_key_blob = wmem_array_new(wmem_file_scope(), 1);
812 global_data->kex_gex_bits_min = wmem_array_new(wmem_file_scope(), 1);
813 global_data->kex_gex_bits_req = wmem_array_new(wmem_file_scope(), 1);
814 global_data->kex_gex_bits_max = wmem_array_new(wmem_file_scope(), 1);
815 global_data->kex_shared_secret = wmem_array_new(wmem_file_scope(), 1);
816 global_data->do_decrypt = true;
817 global_data->ext_ping_openssh_offered = false;
819 conversation_add_proto_data(conversation, proto_ssh, global_data);
822 peer_data = &global_data->peer_data[is_response];
824 ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
825 ssh_tree = proto_item_add_subtree(ti, ett_ssh);
827 version = global_data->version;
829 switch(version) {
830 case SSH_VERSION_UNKNOWN:
831 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
832 break;
833 case SSH_VERSION_1:
834 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
835 break;
836 case SSH_VERSION_2:
837 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
838 break;
842 col_clear(pinfo->cinfo, COL_INFO);
844 while(tvb_reported_length_remaining(tvb, offset)> 0) {
845 bool after_version_start = (peer_data->frame_version_start == 0 ||
846 pinfo->num >= peer_data->frame_version_start);
847 bool before_version_end = (peer_data->frame_version_end == 0 ||
848 pinfo->num <= peer_data->frame_version_end);
850 need_desegmentation = false;
851 last_offset = offset;
853 peer_data->counter++;
855 if (after_version_start && before_version_end &&
856 (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
857 if (peer_data->frame_version_start == 0)
858 peer_data->frame_version_start = pinfo->num;
860 offset = ssh_dissect_protocol(tvb, pinfo,
861 global_data,
862 offset, ssh_tree, is_response,
863 &version, &need_desegmentation);
865 if (!need_desegmentation) {
866 peer_data->frame_version_end = pinfo->num;
867 global_data->version = version;
869 } else {
870 switch(version) {
872 case SSH_VERSION_UNKNOWN:
873 offset = ssh_try_dissect_encrypted_packet(tvb, pinfo,
874 &global_data->peer_data[is_response], offset, ssh_tree);
875 break;
877 case SSH_VERSION_1:
878 offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
879 offset, ssh_tree, is_response,
880 &need_desegmentation);
881 break;
883 case SSH_VERSION_2:
884 offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
885 offset, ssh_tree, is_response,
886 &need_desegmentation);
887 break;
891 if (need_desegmentation)
892 return tvb_captured_length(tvb);
893 if (offset <= last_offset) {
894 /* XXX - add an expert info in the function
895 that decrements offset */
896 break;
900 col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
901 ti = proto_tree_add_boolean_format_value(ssh_tree, hf_ssh_direction, tvb, 0, 0, is_response, "%s",
902 try_val_to_str(is_response, ssh_direction_vals));
903 proto_item_set_generated(ti);
905 ssh_debug_flush();
907 return tvb_captured_length(tvb);
910 static int
911 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
912 struct ssh_flow_data *global_data,
913 int offset, proto_tree *tree, int is_response,
914 bool *need_desegmentation)
916 proto_item *ssh2_tree = NULL;
917 int remain_length;
919 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
921 remain_length = tvb_captured_length_remaining(tvb, offset);
923 while(remain_length>0){
924 int last_offset = offset;
925 if (tree) {
926 wmem_strbuf_t *title = wmem_strbuf_new(pinfo->pool, "SSH Version 2");
928 if (peer_data->enc || peer_data->mac || peer_data->comp) {
929 wmem_strbuf_append_printf(title, " (");
930 if (peer_data->enc)
931 wmem_strbuf_append_printf(title, "encryption:%s%s",
932 peer_data->enc,
933 peer_data->mac || peer_data->comp
934 ? " " : "");
935 if (peer_data->mac)
936 wmem_strbuf_append_printf(title, "mac:%s%s",
937 peer_data->mac,
938 peer_data->comp ? " " : "");
939 if (peer_data->comp)
940 wmem_strbuf_append_printf(title, "compression:%s",
941 peer_data->comp);
942 wmem_strbuf_append_printf(title, ")");
945 ssh2_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title));
947 ws_noisy("....ssh_dissect_ssh2[%c]: frame_key_start=%d, pinfo->num=%d, frame_key_end=%d, offset=%d, frame_key_end_offset=%d ", is_response==SERVER_PEER_DATA?'S':'C', peer_data->frame_key_start, pinfo->num, peer_data->frame_key_end, offset, peer_data->frame_key_end_offset);
948 if ((peer_data->frame_key_start == 0) ||
949 ((peer_data->frame_key_start <= pinfo->num) &&
950 ((peer_data->frame_key_end == 0) || (pinfo->num < peer_data->frame_key_end) ||
951 ((pinfo->num == peer_data->frame_key_end) && (offset < peer_data->frame_key_end_offset))))) {
952 offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
953 offset, ssh2_tree, is_response,
954 need_desegmentation);
956 if (!*need_desegmentation) {
957 ssh_increment_message_number(pinfo, global_data, is_response);
958 }else{
959 break;
961 } else {
962 if(!*need_desegmentation){
963 offset = ssh_try_dissect_encrypted_packet(tvb, pinfo,
964 &global_data->peer_data[is_response], offset, ssh2_tree);
965 }else{
966 break;
970 if (ssh2_tree) {
971 proto_item_set_len(ssh2_tree, offset - last_offset);
974 remain_length = tvb_captured_length_remaining(tvb, offset);
977 return offset;
979 static int
980 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
981 struct ssh_flow_data *global_data,
982 int offset, proto_tree *tree, int is_response,
983 bool *need_desegmentation)
985 unsigned plen, padding_length, len;
986 uint8_t msg_code;
987 unsigned remain_length;
989 proto_item *ssh1_tree;
991 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
993 ssh1_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1");
996 * We use "tvb_ensure_captured_length_remaining()" to make sure there
997 * actually *is* data remaining.
999 * This means we're guaranteed that "remain_length" is positive.
1001 remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1003 * Can we do reassembly?
1005 if (ssh_desegment && pinfo->can_desegment) {
1007 * Yes - would an SSH header starting at this offset be split
1008 * across segment boundaries?
1010 if (remain_length < 4) {
1012 * Yes. Tell the TCP dissector where the data for
1013 * this message starts in the data it handed us and
1014 * that we need "some more data." Don't tell it
1015 * exactly how many bytes we need because if/when we
1016 * ask for even more (after the header) that will
1017 * break reassembly.
1019 pinfo->desegment_offset = offset;
1020 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1021 *need_desegmentation = true;
1022 return offset;
1025 plen = tvb_get_ntohl(tvb, offset) ;
1026 padding_length = 8 - plen%8;
1029 if (ssh_desegment && pinfo->can_desegment) {
1030 if (plen+4+padding_length > remain_length) {
1031 pinfo->desegment_offset = offset;
1032 pinfo->desegment_len = plen+padding_length - remain_length;
1033 *need_desegmentation = true;
1034 return offset;
1038 if (plen >= 0xffff) {
1039 if (ssh1_tree && plen > 0) {
1040 proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
1041 offset, 4, plen, "Overly large length %x", plen);
1043 plen = remain_length-4-padding_length;
1044 } else {
1045 if (ssh1_tree && plen > 0) {
1046 proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
1047 offset, 4, plen);
1050 offset+=4;
1051 /* padding length */
1053 proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
1054 offset, padding_length, padding_length);
1055 offset += padding_length;
1057 /* msg_code */
1058 if ((peer_data->frame_key_start == 0) ||
1059 ((peer_data->frame_key_start >= pinfo->num) && (pinfo->num <= peer_data->frame_key_end))) {
1060 msg_code = tvb_get_uint8(tvb, offset);
1062 proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1063 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1064 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
1065 offset += 1;
1066 len = plen -1;
1067 if (!pinfo->fd->visited) {
1068 if (peer_data->frame_key_start == 0)
1069 peer_data->frame_key_start = pinfo->num;
1070 peer_data->frame_key_end = pinfo->num;
1072 } else {
1073 len = plen;
1074 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
1076 /* payload */
1077 if (ssh1_tree) {
1078 proto_tree_add_item(ssh1_tree, hf_ssh_payload,
1079 tvb, offset, len, ENC_NA);
1081 offset += len;
1083 return offset;
1086 static int
1087 ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
1088 int hf_ssh_mpint_selection)
1090 unsigned len = tvb_get_ntohl(tvb, offset);
1091 proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
1092 offset, 4, len);
1093 offset+=4;
1094 proto_tree_add_item(tree, hf_ssh_mpint_selection,
1095 tvb, offset, len, ENC_NA);
1096 return 4+len;
1099 static int
1100 ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
1101 int hf_ssh_string, int hf_ssh_string_length)
1103 unsigned len = tvb_get_ntohl(tvb, offset);
1104 proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
1105 offset, 4, len);
1106 offset+=4;
1107 proto_tree_add_item(tree, hf_ssh_string,
1108 tvb, offset, len, ENC_NA);
1109 return 4+len;
1112 static unsigned
1113 ssh_tree_add_hostkey(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
1114 const char *tree_name, int ett_idx,
1115 struct ssh_flow_data *global_data)
1117 proto_tree *tree = NULL;
1118 int last_offset;
1119 int remaining_len;
1120 unsigned key_len, type_len;
1121 char* key_type;
1122 char *tree_title;
1124 last_offset = offset;
1126 key_len = tvb_get_ntohl(tvb, offset);
1127 offset += 4;
1129 /* Read the key type before creating the tree so we can append it as info. */
1130 type_len = tvb_get_ntohl(tvb, offset);
1131 offset += 4;
1132 key_type = (char *) tvb_get_string_enc(wmem_packet_scope(), tvb, offset, type_len, ENC_ASCII|ENC_NA);
1134 tree_title = wmem_strdup_printf(wmem_packet_scope(), "%s (type: %s)", tree_name, key_type);
1135 tree = proto_tree_add_subtree(parent_tree, tvb, last_offset, key_len + 4, ett_idx, NULL,
1136 tree_title);
1138 proto_tree_add_uint(tree, hf_ssh_hostkey_length, tvb, last_offset, 4, key_len);
1140 // server host key (K_S / Q)
1141 char *data = (char *)tvb_memdup(wmem_packet_scope(), tvb, last_offset + 4, key_len);
1142 ssh_hash_buffer_put_string(global_data->kex_server_host_key_blob, data, key_len);
1144 last_offset += 4;
1145 proto_tree_add_uint(tree, hf_ssh_hostkey_type_length, tvb, last_offset, 4, type_len);
1146 proto_tree_add_string(tree, hf_ssh_hostkey_type, tvb, offset, type_len, key_type);
1147 offset += type_len;
1149 if (0 == strcmp(key_type, "ssh-rsa")) {
1150 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_e);
1151 ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_n);
1152 } else if (0 == strcmp(key_type, "ssh-dss")) {
1153 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_p);
1154 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_q);
1155 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_g);
1156 ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_y);
1157 } else if (g_str_has_prefix(key_type, "ecdsa-sha2-")) {
1158 offset += ssh_tree_add_string(tvb, offset, tree,
1159 hf_ssh_hostkey_ecdsa_curve_id, hf_ssh_hostkey_ecdsa_curve_id_length);
1160 ssh_tree_add_string(tvb, offset, tree,
1161 hf_ssh_hostkey_ecdsa_q, hf_ssh_hostkey_ecdsa_q_length);
1162 } else if (g_str_has_prefix(key_type, "ssh-ed")) {
1163 ssh_tree_add_string(tvb, offset, tree,
1164 hf_ssh_hostkey_eddsa_key, hf_ssh_hostkey_eddsa_key_length);
1165 } else {
1166 remaining_len = key_len - (type_len + 4);
1167 proto_tree_add_item(tree, hf_ssh_hostkey_data, tvb, offset, remaining_len, ENC_NA);
1170 return 4+key_len;
1173 static unsigned
1174 ssh_tree_add_hostsignature(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree,
1175 const char *tree_name, int ett_idx,
1176 struct ssh_flow_data *global_data)
1178 (void)global_data;
1179 proto_tree *tree = NULL;
1180 proto_item* ti = NULL;
1181 int last_offset;
1182 int offset0 = offset;
1183 int remaining_len;
1184 unsigned sig_len, type_len;
1185 uint8_t* sig_type;
1186 char *tree_title;
1188 last_offset = offset;
1190 sig_len = tvb_get_ntohl(tvb, offset);
1191 offset += 4;
1193 /* Read the signature type before creating the tree so we can append it as info. */
1194 type_len = tvb_get_ntohl(tvb, offset);
1195 offset += 4;
1196 sig_type = tvb_get_string_enc(pinfo->pool, tvb, offset, type_len, ENC_ASCII|ENC_NA);
1198 tree_title = wmem_strdup_printf(pinfo->pool, "%s (type: %s)", tree_name, sig_type);
1199 tree = proto_tree_add_subtree(parent_tree, tvb, last_offset, sig_len + 4, ett_idx, NULL,
1200 tree_title);
1202 ti = proto_tree_add_uint(tree, hf_ssh_hostsig_length, tvb, last_offset, 4, sig_len);
1204 last_offset += 4;
1205 proto_tree_add_uint(tree, hf_ssh_hostsig_type_length, tvb, last_offset, 4, type_len);
1206 proto_tree_add_string(tree, hf_ssh_hostsig_type, tvb, offset, type_len, sig_type);
1207 offset += type_len;
1209 if (0 == strcmp(sig_type, "ssh-rsa")) {
1210 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostsig_rsa);
1211 } else if (0 == strcmp(sig_type, "ssh-dss")) {
1212 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostsig_dsa);
1213 // } else if (g_str_has_prefix(sig_type, "ecdsa-sha2-")) {
1214 // offset += ssh_tree_add_string(tvb, offset, tree,
1215 // hf_ssh_hostkey_ecdsa_curve_id, hf_ssh_hostkey_ecdsa_curve_id_length);
1216 // ssh_tree_add_string(tvb, offset, tree,
1217 // hf_ssh_hostkey_ecdsa_q, hf_ssh_hostkey_ecdsa_q_length);
1218 // } else if (g_str_has_prefix(sig_type, "ssh-ed")) {
1219 // ssh_tree_add_string(tvb, offset, tree,
1220 // hf_ssh_hostkey_eddsa_key, hf_ssh_hostkey_eddsa_key_length);
1221 } else {
1222 remaining_len = sig_len - (type_len + 4);
1223 proto_tree_add_item(tree, hf_ssh_hostsig_data, tvb, offset, remaining_len, ENC_NA);
1224 offset += remaining_len;
1227 if(offset-offset0!=(int)(4+sig_len)){
1228 expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", offset-offset0, sig_len);
1231 return 4+sig_len;
1234 static int
1235 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
1236 struct ssh_flow_data *global_data,
1237 int offset, proto_tree *tree, int is_response,
1238 bool *need_desegmentation)
1240 unsigned plen, len;
1241 uint8_t padding_length;
1242 unsigned remain_length;
1243 int last_offset = offset;
1244 unsigned msg_code;
1245 unsigned seq_num = 0;
1247 proto_item *ti;
1248 proto_item *key_ex_tree = NULL;
1249 const char *key_ex_title = "Key Exchange";
1251 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1254 * We use "tvb_ensure_captured_length_remaining()" to make sure there
1255 * actually *is* data remaining.
1257 * This means we're guaranteed that "remain_length" is positive.
1259 remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1261 * Can we do reassembly?
1263 if (ssh_desegment && pinfo->can_desegment) {
1265 * Yes - would an SSH header starting at this offset
1266 * be split across segment boundaries?
1268 if (remain_length < 4) {
1270 * Yes. Tell the TCP dissector where the data for
1271 * this message starts in the data it handed us and
1272 * that we need "some more data." Don't tell it
1273 * exactly how many bytes we need because if/when we
1274 * ask for even more (after the header) that will
1275 * break reassembly.
1277 pinfo->desegment_offset = offset;
1278 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1279 *need_desegmentation = true;
1280 return offset;
1283 plen = tvb_get_ntohl(tvb, offset) ;
1285 if (ssh_desegment && pinfo->can_desegment) {
1286 if (plen +4 > remain_length) {
1287 pinfo->desegment_offset = offset;
1288 pinfo->desegment_len = plen+4 - remain_length;
1289 *need_desegmentation = true;
1290 return offset;
1294 * Need to check plen > 0x80000000 here
1297 ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
1298 offset, 4, plen);
1299 if (plen >= 0xffff) {
1300 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
1301 plen = remain_length-4;
1303 offset+=4;
1305 /* padding length */
1306 padding_length = tvb_get_uint8(tvb, offset);
1307 proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
1308 offset += 1;
1310 if (global_data->kex)
1311 key_ex_title = wmem_strdup_printf(pinfo->pool, "%s (method:%s)", key_ex_title, global_data->kex);
1312 key_ex_tree = proto_tree_add_subtree(tree, tvb, offset, plen-1, ett_key_exchange, NULL, key_ex_title);
1314 /* msg_code */
1315 msg_code = tvb_get_uint8(tvb, offset);
1317 if (msg_code >= 30 && msg_code < 40) {
1318 offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo,
1319 offset, key_ex_tree, global_data, &seq_num);
1320 } else {
1321 proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1322 offset += 1;
1324 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1325 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
1327 /* 16 bytes cookie */
1328 switch(msg_code)
1330 case SSH_MSG_KEXINIT:
1331 offset = ssh_dissect_key_init(tvb, pinfo, offset, key_ex_tree, is_response, global_data);
1332 if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->num)) {
1333 if (!PINFO_FD_VISITED(pinfo)) {
1334 peer_data->frame_key_start = pinfo->num;
1335 if(global_data->peer_data[is_response].seq_num_kex_init == 0){
1336 global_data->peer_data[is_response].seq_num_kex_init = global_data->peer_data[is_response].sequence_number;
1337 global_data->peer_data[is_response].sequence_number++;
1338 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEXINIT=%d}++ > %d\n", is_response?"server":"client", global_data->peer_data[is_response].seq_num_kex_init, global_data->peer_data[is_response].sequence_number);
1342 seq_num = global_data->peer_data[is_response].seq_num_kex_init;
1343 break;
1344 case SSH_MSG_NEWKEYS:
1345 if (peer_data->frame_key_end == 0) {
1346 peer_data->frame_key_end = pinfo->num;
1347 peer_data->frame_key_end_offset = offset;
1349 if(global_data->peer_data[is_response].seq_num_new_key == 0){
1350 global_data->peer_data[is_response].seq_num_new_key = global_data->peer_data[is_response].sequence_number;
1351 global_data->peer_data[is_response].sequence_number++;
1352 ssh_debug_printf("%s->sequence_number{SSH_MSG_NEWKEYS=%d}++ > %d\n", is_response?"server":"client", global_data->peer_data[is_response].seq_num_new_key, global_data->peer_data[is_response].sequence_number);
1355 // the client sent SSH_MSG_NEWKEYS
1356 if (!is_response) {
1357 ssh_debug_printf("Activating new keys for CLIENT => SERVER\n");
1358 ssh_decryption_setup_cipher(&global_data->peer_data[CLIENT_PEER_DATA], &global_data->new_keys[0], &global_data->new_keys[2]);
1359 ssh_decryption_setup_mac(&global_data->peer_data[CLIENT_PEER_DATA], &global_data->new_keys[4]);
1360 }else{
1361 ssh_debug_printf("Activating new keys for SERVER => CLIENT\n");
1362 ssh_decryption_setup_cipher(&global_data->peer_data[SERVER_PEER_DATA], &global_data->new_keys[1], &global_data->new_keys[3]);
1363 ssh_decryption_setup_mac(&global_data->peer_data[SERVER_PEER_DATA], &global_data->new_keys[5]);
1366 seq_num = global_data->peer_data[is_response].seq_num_new_key;
1368 break;
1372 len = plen+4-padding_length-(offset-last_offset);
1373 if (len > 0) {
1374 proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
1376 offset += len;
1378 /* padding */
1379 proto_tree_add_item(tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
1380 offset+= padding_length;
1381 ti = proto_tree_add_uint(tree, hf_ssh_seq_num, tvb, offset, 0, seq_num);
1382 proto_item_set_generated(ti);
1384 return offset;
1387 static int ssh_dissect_kex_dh(uint8_t msg_code, tvbuff_t *tvb,
1388 packet_info *pinfo, int offset, proto_tree *tree,
1389 struct ssh_flow_data *global_data, unsigned *seq_num)
1391 *seq_num = 0;
1392 proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1393 offset += 1;
1395 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1396 val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
1398 switch (msg_code) {
1399 case SSH_MSG_KEXDH_INIT:
1400 // e (client ephemeral key public part)
1401 if (!ssh_read_e(tvb, offset, global_data)) {
1402 proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1403 "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1406 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
1407 if(global_data->peer_data[CLIENT_PEER_DATA].seq_num_dh_ini == 0){
1408 global_data->peer_data[CLIENT_PEER_DATA].sequence_number++;
1409 global_data->peer_data[CLIENT_PEER_DATA].seq_num_dh_ini = global_data->peer_data[CLIENT_PEER_DATA].sequence_number;
1410 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEXDH_INIT}++ > %d\n", CLIENT_PEER_DATA?"serveur":"client", global_data->peer_data[CLIENT_PEER_DATA].sequence_number);
1412 *seq_num = global_data->peer_data[CLIENT_PEER_DATA].seq_num_dh_ini;
1413 break;
1415 case SSH_MSG_KEXDH_REPLY:
1416 offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1417 ett_key_exchange_host_key, global_data);
1419 // f (server ephemeral key public part), K_S (host key)
1420 if (!ssh_read_f(tvb, offset, global_data)) {
1421 proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1422 "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1424 ssh_choose_enc_mac(global_data);
1425 ssh_keylog_hash_write_secret(global_data);
1427 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
1428 offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
1429 ett_key_exchange_host_sig, global_data);
1430 if(global_data->peer_data[SERVER_PEER_DATA].seq_num_dh_rep == 0){
1431 global_data->peer_data[SERVER_PEER_DATA].sequence_number++;
1432 global_data->peer_data[SERVER_PEER_DATA].seq_num_dh_rep = global_data->peer_data[SERVER_PEER_DATA].sequence_number;
1433 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEXDH_REPLY}++ > %d\n", SERVER_PEER_DATA?"serveur":"client", global_data->peer_data[SERVER_PEER_DATA].sequence_number);
1435 *seq_num = global_data->peer_data[SERVER_PEER_DATA].seq_num_dh_rep;
1436 break;
1439 return offset;
1442 static int ssh_dissect_kex_dh_gex(uint8_t msg_code, tvbuff_t *tvb,
1443 packet_info *pinfo, int offset, proto_tree *tree,
1444 struct ssh_flow_data *global_data, unsigned *seq_num)
1446 *seq_num = 0;
1447 proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1448 offset += 1;
1450 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1451 val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
1453 switch (msg_code) {
1454 case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
1455 proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1456 offset += 4;
1457 break;
1459 case SSH_MSG_KEX_DH_GEX_GROUP:
1460 // p (Group modulo)
1461 global_data->kex_gex_p = ssh_read_mpint(tvb, offset);
1462 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_p);
1463 // g (Group generator)
1464 global_data->kex_gex_g = ssh_read_mpint(tvb, offset);
1465 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_g);
1466 if(global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_grp == 0){
1467 global_data->peer_data[SERVER_PEER_DATA].sequence_number++;
1468 global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_grp = global_data->peer_data[SERVER_PEER_DATA].sequence_number;
1469 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEX_DH_GEX_GROUP}++ > %d\n", SERVER_PEER_DATA?"serveur":"client", global_data->peer_data[SERVER_PEER_DATA].sequence_number);
1471 *seq_num = global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_grp;
1472 break;
1474 case SSH_MSG_KEX_DH_GEX_INIT:
1475 // e (Client public key)
1476 if (!ssh_read_e(tvb, offset, global_data)) {
1477 proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1478 "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1480 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
1481 if(global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_ini == 0){
1482 global_data->peer_data[CLIENT_PEER_DATA].sequence_number++;
1483 global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_ini = global_data->peer_data[CLIENT_PEER_DATA].sequence_number;
1484 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEX_DH_GEX_INIT}++ > %d\n", CLIENT_PEER_DATA?"serveur":"client", global_data->peer_data[CLIENT_PEER_DATA].sequence_number);
1486 *seq_num = global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_ini;
1487 break;
1489 case SSH_MSG_KEX_DH_GEX_REPLY:
1490 offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1491 ett_key_exchange_host_key, global_data);
1492 if (!PINFO_FD_VISITED(pinfo)) {
1493 ssh_read_f(tvb, offset, global_data);
1494 // f (server ephemeral key public part), K_S (host key)
1495 ssh_choose_enc_mac(global_data);
1496 ssh_keylog_hash_write_secret(global_data);
1498 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
1499 offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
1500 ett_key_exchange_host_sig, global_data);
1501 if(global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_rep == 0){
1502 global_data->peer_data[SERVER_PEER_DATA].sequence_number++;
1503 global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_rep = global_data->peer_data[SERVER_PEER_DATA].sequence_number;
1504 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEX_DH_GEX_REPLY}++ > %d\n", SERVER_PEER_DATA?"serveur":"client", global_data->peer_data[SERVER_PEER_DATA].sequence_number);
1506 *seq_num = global_data->peer_data[SERVER_PEER_DATA].seq_num_gex_rep;
1507 break;
1509 case SSH_MSG_KEX_DH_GEX_REQUEST:{
1511 if (!PINFO_FD_VISITED(pinfo)) {
1512 ssh_hash_buffer_put_uint32(global_data->kex_gex_bits_min, tvb_get_ntohl(tvb, offset));
1514 proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
1515 offset += 4;
1516 if (!PINFO_FD_VISITED(pinfo)) {
1517 ssh_hash_buffer_put_uint32(global_data->kex_gex_bits_req, tvb_get_ntohl(tvb, offset));
1519 proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1520 offset += 4;
1521 if (!PINFO_FD_VISITED(pinfo)) {
1522 ssh_hash_buffer_put_uint32(global_data->kex_gex_bits_max, tvb_get_ntohl(tvb, offset));
1524 proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
1525 offset += 4;
1526 if(global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_req == 0){
1527 global_data->peer_data[CLIENT_PEER_DATA].sequence_number++;
1528 global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_req = global_data->peer_data[CLIENT_PEER_DATA].sequence_number;
1529 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEX_DH_GEX_REQUEST}++ > %d\n", CLIENT_PEER_DATA?"serveur":"client", global_data->peer_data[CLIENT_PEER_DATA].sequence_number);
1531 *seq_num = global_data->peer_data[CLIENT_PEER_DATA].seq_num_gex_req;
1532 break;
1536 return offset;
1539 static int
1540 ssh_dissect_kex_ecdh(uint8_t msg_code, tvbuff_t *tvb,
1541 packet_info *pinfo, int offset, proto_tree *tree,
1542 struct ssh_flow_data *global_data, unsigned *seq_num)
1544 proto_tree_add_item(tree, hf_ssh2_kex_ecdh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1545 offset += 1;
1547 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1548 val_to_str(msg_code, ssh2_kex_ecdh_msg_vals, "Unknown (%u)"));
1550 switch (msg_code) {
1551 case SSH_MSG_KEX_ECDH_INIT:
1552 if (!ssh_read_e(tvb, offset, global_data)) {
1553 proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1554 "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1557 if (!PINFO_FD_VISITED(pinfo)) {
1558 if(global_data->peer_data[CLIENT_PEER_DATA].seq_num_ecdh_ini == 0){
1559 global_data->peer_data[CLIENT_PEER_DATA].seq_num_ecdh_ini = global_data->peer_data[CLIENT_PEER_DATA].sequence_number;
1560 global_data->peer_data[CLIENT_PEER_DATA].sequence_number++;
1561 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEX_ECDH_INIT=%d}++ > %d\n", CLIENT_PEER_DATA?"server":"client", global_data->peer_data[CLIENT_PEER_DATA].seq_num_ecdh_ini, global_data->peer_data[CLIENT_PEER_DATA].sequence_number);
1564 *seq_num = global_data->peer_data[CLIENT_PEER_DATA].seq_num_ecdh_ini;
1566 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_c, hf_ssh_ecdh_q_c_length);
1567 break;
1569 case SSH_MSG_KEX_ECDH_REPLY:
1570 offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1571 ett_key_exchange_host_key, global_data);
1573 if (!ssh_read_f(tvb, offset, global_data)){
1574 proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1575 "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1578 ssh_choose_enc_mac(global_data);
1579 ssh_keylog_hash_write_secret(global_data);
1580 if(global_data->peer_data[SERVER_PEER_DATA].seq_num_ecdh_rep == 0){
1581 global_data->peer_data[SERVER_PEER_DATA].seq_num_ecdh_rep = global_data->peer_data[SERVER_PEER_DATA].sequence_number;
1582 global_data->peer_data[SERVER_PEER_DATA].sequence_number++;
1583 ssh_debug_printf("%s->sequence_number{SSH_MSG_KEX_ECDH_REPLY=%d}++ > %d\n", SERVER_PEER_DATA?"server":"client", global_data->peer_data[SERVER_PEER_DATA].seq_num_ecdh_rep, global_data->peer_data[SERVER_PEER_DATA].sequence_number);
1585 *seq_num = global_data->peer_data[SERVER_PEER_DATA].seq_num_ecdh_rep;
1587 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_s, hf_ssh_ecdh_q_s_length);
1588 offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
1589 ett_key_exchange_host_sig, global_data);
1590 break;
1593 return offset;
1596 static ssh_message_info_t*
1597 ssh_get_message(packet_info *pinfo, int record_id)
1599 ssh_packet_info_t *packet = (ssh_packet_info_t *)p_get_proto_data(
1600 wmem_file_scope(), pinfo, proto_ssh, 0);
1602 if (!packet) {
1603 return NULL;
1606 ssh_message_info_t *message = NULL;
1607 for (message = packet->messages; message; message = message->next) {
1608 ws_debug("%u:looking for message %d now %d", pinfo->num, record_id, message->id);
1609 if (message->id == record_id) {
1610 return message;
1614 return NULL;
1617 static int
1618 ssh_try_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
1619 struct ssh_peer_data *peer_data, int offset, proto_tree *tree)
1621 bool can_decrypt = peer_data->cipher != NULL;
1622 ssh_message_info_t *message = NULL;
1624 if (can_decrypt) {
1625 if (!PINFO_FD_VISITED(pinfo)) {
1626 ssh_decrypt_packet(tvb, pinfo, peer_data, offset);
1629 int record_id = tvb_raw_offset(tvb) + offset;
1630 message = ssh_get_message(pinfo, record_id);
1632 if (message) {
1633 offset += ssh_dissect_decrypted_packet(tvb_new_subset_remaining(tvb, offset), pinfo, peer_data, tree, message);
1634 return offset;
1638 return ssh_dissect_encrypted_packet(tvb, pinfo, peer_data, offset, tree);
1641 static int
1642 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
1643 struct ssh_peer_data *peer_data,
1644 int offset, proto_tree *tree)
1646 int len;
1647 unsigned plen;
1649 len = tvb_reported_length_remaining(tvb, offset);
1650 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
1652 if (tree) {
1653 int encrypted_len = len;
1655 if (len > 4 && peer_data->length_is_plaintext) {
1656 plen = tvb_get_ntohl(tvb, offset) ;
1657 proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
1658 encrypted_len -= 4;
1660 else if (len > 4) {
1661 proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
1662 encrypted_len -= 4;
1665 if (peer_data->mac_length>0)
1666 encrypted_len -= peer_data->mac_length;
1668 proto_tree_add_item(tree, hf_ssh_encrypted_packet,
1669 tvb, offset+4, encrypted_len, ENC_NA);
1671 if (peer_data->mac_length>0)
1672 proto_tree_add_item(tree, hf_ssh_mac_string,
1673 tvb, offset+4+encrypted_len,
1674 peer_data->mac_length, ENC_NA);
1676 offset += len;
1677 return offset;
1680 static int
1681 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
1682 struct ssh_flow_data *global_data,
1683 int offset, proto_tree *tree, int is_response, unsigned * version,
1684 bool *need_desegmentation)
1686 unsigned remain_length;
1687 int linelen, protolen;
1690 * If the first packet do not contain the banner,
1691 * it is dump in the middle of a flow or not a ssh at all
1693 if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
1694 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
1695 &global_data->peer_data[is_response], offset, tree);
1696 return offset;
1699 if (!is_response) {
1700 if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
1701 *(version) = SSH_VERSION_2;
1702 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
1703 *(version) = SSH_VERSION_2;
1704 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
1705 *(version) = SSH_VERSION_1;
1710 * We use "tvb_ensure_captured_length_remaining()" to make sure there
1711 * actually *is* data remaining.
1713 * This means we're guaranteed that "remain_length" is positive.
1715 remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1716 /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, false);
1718 linelen = tvb_find_uint8(tvb, offset, -1, '\n');
1720 if (ssh_desegment && pinfo->can_desegment) {
1721 if (linelen == -1 || remain_length < (unsigned)linelen-offset) {
1722 pinfo->desegment_offset = offset;
1723 pinfo->desegment_len = linelen-remain_length;
1724 *need_desegmentation = true;
1725 return offset;
1728 if (linelen == -1) {
1729 /* XXX - reassemble across segment boundaries? */
1730 linelen = remain_length;
1731 protolen = linelen;
1732 } else {
1733 linelen = linelen - offset + 1;
1735 if (linelen > 1 && tvb_get_uint8(tvb, offset + linelen - 2) == '\r')
1736 protolen = linelen - 2;
1737 else
1738 protolen = linelen - 1;
1741 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
1742 tvb_format_text(pinfo->pool, tvb, offset, protolen));
1744 // V_C / V_S (client and server identification strings) RFC4253 4.2
1745 // format: SSH-protoversion-softwareversion SP comments [CR LF not incl.]
1746 if (!PINFO_FD_VISITED(pinfo)) {
1747 char *data = (char *)tvb_memdup(pinfo->pool, tvb, offset, protolen);
1748 if(!is_response){
1749 ssh_hash_buffer_put_string(global_data->kex_client_version, data, protolen);
1750 }else{
1751 ssh_hash_buffer_put_string(global_data->kex_server_version, data, protolen);
1755 proto_tree_add_item(tree, hf_ssh_protocol,
1756 tvb, offset, protolen, ENC_ASCII);
1757 offset += linelen;
1758 return offset;
1761 static void
1762 ssh_set_mac_length(struct ssh_peer_data *peer_data)
1764 char *size_str;
1765 uint32_t size = 0;
1766 char *mac_name = peer_data->mac;
1767 char *strip;
1769 if (!mac_name)
1770 return;
1772 /* wmem_strdup() never returns NULL */
1773 mac_name = wmem_strdup(NULL, (const char *)mac_name);
1775 /* strip trailing "-etm@openssh.com" or "@openssh.com" */
1776 strip = strstr(mac_name, "-etm@openssh.com");
1777 if (strip) {
1778 peer_data->length_is_plaintext = 1;
1779 *strip = '\0';
1781 else {
1782 strip = strstr(mac_name, "@openssh.com");
1783 if (strip) *strip = '\0';
1786 size_str = g_strrstr(mac_name, "-");
1787 if (size_str && ws_strtou32(size_str + 1, NULL, &size) && size > 0 && size % 8 == 0) {
1788 peer_data->mac_length = size / 8;
1790 else if (strcmp(mac_name, "hmac-sha1") == 0) {
1791 peer_data->mac_length = 20;
1793 else if (strcmp(mac_name, "hmac-md5") == 0) {
1794 peer_data->mac_length = 16;
1796 else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
1797 peer_data->mac_length = 20;
1799 else if (strcmp(mac_name, "none") == 0) {
1800 peer_data->mac_length = 0;
1803 wmem_free(NULL, mac_name);
1806 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
1808 const char *kex_name = global_data->kex;
1810 if (!kex_name) return;
1812 if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
1813 strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
1815 global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
1817 else if (g_str_has_prefix(kex_name, "ecdh-sha2-") ||
1818 strcmp(kex_name, "curve25519-sha256@libssh.org") == 0 ||
1819 strcmp(kex_name, "curve25519-sha256") == 0 ||
1820 strcmp(kex_name, "curve448-sha512") == 0)
1822 global_data->kex_specific_dissector = ssh_dissect_kex_ecdh;
1824 else if (strcmp(kex_name, "diffie-hellman-group14-sha256") == 0 ||
1825 strcmp(kex_name, "diffie-hellman-group16-sha512") == 0 ||
1826 strcmp(kex_name, "diffie-hellman-group18-sha512") == 0 ||
1827 strcmp(kex_name, "diffie-hellman-group1-sha1") == 0 ||
1828 strcmp(kex_name, "diffie-hellman-group14-sha1") == 0)
1830 global_data->kex_specific_dissector = ssh_dissect_kex_dh;
1834 static int
1835 ssh_gslist_compare_strings(const void *a, const void *b)
1837 if (a == NULL && b == NULL)
1838 return 0;
1839 if (a == NULL)
1840 return -1;
1841 if (b == NULL)
1842 return 1;
1843 return strcmp((const char*)a, (const char*)b);
1846 /* expects that *result is NULL */
1847 static void
1848 ssh_choose_algo(char *client, char *server, char **result)
1850 char **server_strings = NULL;
1851 char **client_strings = NULL;
1852 char **step;
1853 GSList *server_list = NULL;
1855 if (!client || !server || !result || *result)
1856 return;
1858 server_strings = g_strsplit(server, ",", 0);
1859 for (step = server_strings; *step; step++) {
1860 server_list = g_slist_append(server_list, *step);
1863 client_strings = g_strsplit(client, ",", 0);
1864 for (step = client_strings; *step; step++) {
1865 GSList *agreed;
1866 if ((agreed = g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
1867 *result = wmem_strdup(wmem_file_scope(), (const char *)agreed->data);
1868 break;
1872 g_strfreev(client_strings);
1873 g_slist_free(server_list);
1874 g_strfreev(server_strings);
1877 static int
1878 ssh_dissect_key_init(tvbuff_t *tvb, packet_info *pinfo, int offset,
1879 proto_tree *tree, int is_response, struct ssh_flow_data *global_data)
1881 int start_offset = offset;
1882 int payload_length;
1883 wmem_strbuf_t *hassh_algo;
1884 char *hassh;
1886 proto_item *tf, *ti;
1887 proto_tree *key_init_tree;
1889 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1891 key_init_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
1892 if (!PINFO_FD_VISITED(pinfo)) {
1893 peer_data->bn_cookie = ssh_kex_make_bignum(tvb_get_ptr(tvb, offset, 16), 16);
1895 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
1896 tvb, offset, 16, ENC_NA);
1897 offset += 16;
1899 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1900 hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
1901 &peer_data->kex_proposal);
1902 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1903 hf_ssh_server_host_key_algorithms_length,
1904 hf_ssh_server_host_key_algorithms, NULL);
1905 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1906 hf_ssh_encryption_algorithms_client_to_server_length,
1907 hf_ssh_encryption_algorithms_client_to_server,
1908 &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1909 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1910 hf_ssh_encryption_algorithms_server_to_client_length,
1911 hf_ssh_encryption_algorithms_server_to_client,
1912 &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1913 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1914 hf_ssh_mac_algorithms_client_to_server_length,
1915 hf_ssh_mac_algorithms_client_to_server,
1916 &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1917 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1918 hf_ssh_mac_algorithms_server_to_client_length,
1919 hf_ssh_mac_algorithms_server_to_client,
1920 &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1921 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1922 hf_ssh_compression_algorithms_client_to_server_length,
1923 hf_ssh_compression_algorithms_client_to_server,
1924 &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1925 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1926 hf_ssh_compression_algorithms_server_to_client_length,
1927 hf_ssh_compression_algorithms_server_to_client,
1928 &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1929 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1930 hf_ssh_languages_client_to_server_length,
1931 hf_ssh_languages_client_to_server, NULL);
1932 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1933 hf_ssh_languages_server_to_client_length,
1934 hf_ssh_languages_server_to_client, NULL);
1936 proto_tree_add_item(key_init_tree, hf_ssh_first_kex_packet_follows,
1937 tvb, offset, 1, ENC_BIG_ENDIAN);
1938 offset+=1;
1940 proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
1941 tvb, offset, 4, ENC_NA);
1942 offset+=4;
1944 hassh_algo = wmem_strbuf_new(pinfo->pool, "");
1945 if(!is_response) {
1946 wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL],
1947 peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL], peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1948 hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
1949 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
1950 proto_item_set_generated(ti);
1951 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh, tvb, offset, 0, hassh);
1952 proto_item_set_generated(ti);
1953 g_free(hassh);
1954 } else {
1955 wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL],
1956 peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL], peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1957 hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
1958 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
1959 proto_item_set_generated(ti);
1960 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver, tvb, offset, 0, hassh);
1961 proto_item_set_generated(ti);
1962 g_free(hassh);
1965 if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
1966 global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
1967 !global_data->kex)
1969 /* Note: we're ignoring first_kex_packet_follows. */
1970 ssh_choose_algo(
1971 global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
1972 global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
1973 &global_data->kex);
1974 ssh_set_kex_specific_dissector(global_data);
1977 payload_length = offset - start_offset;
1979 if (tf != NULL) {
1980 proto_item_set_len(tf, payload_length);
1983 // I_C / I_S (client and server SSH_MSG_KEXINIT payload) RFC4253 4.2
1984 if (!PINFO_FD_VISITED(pinfo)) {
1985 char *data = (char *)wmem_alloc(pinfo->pool, payload_length + 1);
1986 tvb_memcpy(tvb, data + 1, start_offset, payload_length);
1987 data[0] = SSH_MSG_KEXINIT;
1988 if(is_response){
1989 ssh_hash_buffer_put_string(global_data->kex_server_key_exchange_init, data, payload_length + 1);
1990 }else{
1991 ssh_hash_buffer_put_string(global_data->kex_client_key_exchange_init, data, payload_length + 1);
1995 return offset;
1998 static int
1999 ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
2000 int hf_index_length, int hf_index_value, char **store)
2002 uint32_t len = tvb_get_ntohl(tvb, offset);
2003 proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
2004 offset += 4;
2006 proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
2007 ENC_ASCII);
2008 if (store)
2009 *store = (char *) tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
2010 offset += len;
2012 return offset;
2015 static void
2016 ssh_keylog_read_file(void)
2018 if (!pref_keylog_file || !*pref_keylog_file) {
2019 ws_debug("no keylog file preference set");
2020 return;
2023 if (ssh_keylog_file && file_needs_reopen(ws_fileno(ssh_keylog_file),
2024 pref_keylog_file)) {
2025 ssh_keylog_reset();
2026 g_hash_table_remove_all(ssh_master_key_map);
2029 if (!ssh_keylog_file) {
2030 ssh_keylog_file = ws_fopen(pref_keylog_file, "r");
2031 if (!ssh_keylog_file) {
2032 ws_debug("ssh: failed to open key log file %s: %s",
2033 pref_keylog_file, g_strerror(errno));
2034 return;
2038 /* File format: each line follows the format "<cookie> <type> <key>".
2039 * <cookie> is the hex-encoded (client or server) 16 bytes cookie
2040 * (32 characters) found in the SSH_MSG_KEXINIT of the endpoint whose
2041 * private random is disclosed.
2042 * <type> is either SHARED_SECRET or PRIVATE_KEY depending on the
2043 * type of key provided. PRIVAT_KEY is only supported for DH,
2044 * DH group exchange, and ECDH (including Curve25519) key exchanges.
2045 * <key> is the private random number that is used to generate the DH
2046 * negotiation (length depends on algorithm). In RFC4253 it is called
2047 * x for the client and y for the server.
2048 * For openssh and DH group exchange, it can be retrieved using
2049 * DH_get0_key(kex->dh, NULL, &server_random)
2050 * for groupN in file kexdh.c function kex_dh_compute_key
2051 * for custom group in file kexgexs.c function input_kex_dh_gex_init
2052 * For openssh and curve25519, it can be found in function kex_c25519_enc
2053 * in variable server_key. One may also provide the shared secret
2054 * directly if <type> is set to SHARED_SECRET.
2056 * Example:
2057 * 90d886612f9c35903db5bb30d11f23c2 PRIVATE_KEY DEF830C22F6C927E31972FFB20B46C96D0A5F2D5E7BE5A3A8804D6BFC431619ED10AF589EEDFF4750DEA00EFD7AFDB814B6F3528729692B1F2482041521AE9DC
2059 for (;;) {
2060 char buf[512];
2061 buf[0] = 0;
2063 if (!fgets(buf, sizeof(buf), ssh_keylog_file)) {
2064 if (ferror(ssh_keylog_file)) {
2065 ws_debug("Error while reading %s, closing it.", pref_keylog_file);
2066 ssh_keylog_reset();
2067 g_hash_table_remove_all(ssh_master_key_map);
2069 break;
2072 size_t len = strlen(buf);
2073 while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n')){len-=1;buf[len]=0;}
2075 ssh_keylog_process_line(buf);
2079 static void
2080 ssh_keylog_process_lines(const uint8_t *data, unsigned datalen)
2082 const char *next_line = (const char *)data;
2083 const char *line_end = next_line + datalen;
2084 while (next_line && next_line < line_end) {
2085 const char *line = next_line;
2086 next_line = (const char *)memchr(line, '\n', line_end - line);
2087 ssize_t linelen;
2089 if (next_line) {
2090 linelen = next_line - line;
2091 next_line++; /* drop LF */
2092 } else {
2093 linelen = (ssize_t)(line_end - line);
2095 if (linelen > 0 && line[linelen - 1] == '\r') {
2096 linelen--; /* drop CR */
2099 ssh_debug_printf(" checking keylog line: %.*s\n", (int)linelen, line);
2101 char * strippedline = g_strndup(line, linelen);
2102 ssh_keylog_process_line(strippedline);
2103 g_free(strippedline);
2107 static void
2108 ssh_keylog_process_line(const char *line)
2110 ws_noisy("ssh: process line: %s", line);
2112 char **split = g_strsplit(line, " ", 3);
2113 char *cookie, *type, *key;
2114 size_t cookie_len, key_len;
2116 if (g_strv_length(split) == 3) {
2117 // New format: [hex-encoded cookie] [key type] [hex-encoded key material]
2118 cookie = split[0];
2119 type = split[1];
2120 key = split[2];
2121 } else if (g_strv_length(split) == 2) {
2122 // Old format: [hex-encoded cookie] [hex-encoded private key]
2123 ws_debug("ssh keylog: detected old keylog format without explicit key type");
2124 type = "PRIVATE_KEY";
2125 cookie = split[0];
2126 key = split[1];
2127 } else {
2128 ws_debug("ssh keylog: invalid format");
2129 g_strfreev(split);
2130 return;
2133 key_len = strlen(key);
2134 cookie_len = strlen(cookie);
2135 if(key_len & 1){
2136 ws_debug("ssh keylog: invalid format (key could at least be even!)");
2137 g_strfreev(split);
2138 return;
2140 if(cookie_len & 1){
2141 ws_debug("ssh keylog: invalid format (cookie could at least be even!)");
2142 g_strfreev(split);
2143 return;
2145 ssh_bignum * bn_cookie = ssh_kex_make_bignum(NULL, (unsigned)(cookie_len/2));
2146 ssh_bignum * bn_priv = ssh_kex_make_bignum(NULL, (unsigned)(key_len/2));
2147 uint8_t c;
2148 for (size_t i = 0; i < key_len/2; i ++) {
2149 char v0 = key[i * 2];
2150 int8_t h0 = (v0>='0' && v0<='9')?v0-'0':(v0>='a' && v0<='f')?v0-'a'+10:(v0>='A' && v0<='F')?v0-'A'+10:-1;
2151 char v1 = key[i * 2 + 1];
2152 int8_t h1 = (v1>='0' && v1<='9')?v1-'0':(v1>='a' && v1<='f')?v1-'a'+10:(v1>='A' && v1<='F')?v1-'A'+10:-1;
2154 if (h0==-1 || h1==-1) {
2155 ws_debug("ssh: can't process key, invalid hex number: %c%c", v0, v1);
2156 g_strfreev(split);
2157 return;
2160 c = (h0 << 4) | h1;
2162 bn_priv->data[i] = c;
2164 for (size_t i = 0; i < cookie_len/2; i ++) {
2165 char v0 = cookie[i * 2];
2166 int8_t h0 = (v0>='0' && v0<='9')?v0-'0':(v0>='a' && v0<='f')?v0-'a'+10:(v0>='A' && v0<='F')?v0-'A'+10:-1;
2167 char v1 = cookie[i * 2 + 1];
2168 int8_t h1 = (v1>='0' && v1<='9')?v1-'0':(v1>='a' && v1<='f')?v1-'a'+10:(v1>='A' && v1<='F')?v1-'A'+10:-1;
2170 if (h0==-1 || h1==-1) {
2171 ws_debug("ssh: can't process cookie, invalid hex number: %c%c", v0, v1);
2172 g_strfreev(split);
2173 return;
2176 c = (h0 << 4) | h1;
2178 bn_cookie->data[i] = c;
2180 ssh_bignum * bn_priv_ht = g_new(ssh_bignum, 1);
2181 bn_priv_ht->length = bn_priv->length;
2182 bn_priv_ht->data = (uint8_t *) g_memdup2(bn_priv->data, bn_priv->length);
2183 ssh_bignum * bn_cookie_ht = g_new(ssh_bignum, 1);
2184 bn_cookie_ht->length = bn_cookie->length;
2185 bn_cookie_ht->data = (uint8_t *) g_memdup2(bn_cookie->data, bn_cookie->length);
2187 char * type_ht = (char *) g_memdup2(type, strlen(type) + 1);
2188 ssh_key_map_entry_t * entry_ht = g_new(ssh_key_map_entry_t, 1);
2189 entry_ht->type = type_ht;
2190 entry_ht->key_material = bn_priv_ht;
2191 g_hash_table_insert(ssh_master_key_map, bn_cookie_ht, entry_ht);
2192 g_strfreev(split);
2195 static void
2196 ssh_keylog_reset(void)
2198 if (ssh_keylog_file) {
2199 fclose(ssh_keylog_file);
2200 ssh_keylog_file = NULL;
2204 static unsigned
2205 ssh_kex_type(char *type)
2207 if (type) {
2208 if (g_str_has_prefix(type, "curve25519")) {
2209 return SSH_KEX_CURVE25519;
2210 }else if (g_str_has_prefix(type, "diffie-hellman-group-exchange")) {
2211 return SSH_KEX_DH_GEX;
2212 }else if (g_str_has_prefix(type, "diffie-hellman-group14")) {
2213 return SSH_KEX_DH_GROUP14;
2214 }else if (g_str_has_prefix(type, "diffie-hellman-group16")) {
2215 return SSH_KEX_DH_GROUP16;
2216 }else if (g_str_has_prefix(type, "diffie-hellman-group18")) {
2217 return SSH_KEX_DH_GROUP18;
2218 }else if (g_str_has_prefix(type, "diffie-hellman-group1")) {
2219 return SSH_KEX_DH_GROUP1;
2223 return 0;
2226 static unsigned
2227 ssh_kex_hash_type(char *type_string)
2229 if (type_string && g_str_has_suffix(type_string, "sha1")) {
2230 return SSH_KEX_HASH_SHA1;
2231 }else if (type_string && g_str_has_suffix(type_string, "sha256")) {
2232 return SSH_KEX_HASH_SHA256;
2233 }else if (type_string && g_str_has_suffix(type_string, "sha256@libssh.org")) {
2234 return SSH_KEX_HASH_SHA256;
2235 }else if (type_string && g_str_has_suffix(type_string, "sha512")) {
2236 return SSH_KEX_HASH_SHA512;
2237 } else {
2238 ws_debug("hash type %s not supported", type_string);
2239 return 0;
2243 static ssh_bignum *
2244 ssh_kex_make_bignum(const uint8_t *data, unsigned length)
2246 // 512 bytes (4096 bits) is the maximum bignum size we're supporting
2247 // Actually we need 513 bytes, to make provision for signed values
2248 // Diffie-Hellman group 18 has 8192 bits
2249 if (length == 0 || length > 1025) {
2250 return NULL;
2253 ssh_bignum *bn = wmem_new0(wmem_file_scope(), ssh_bignum);
2254 bn->data = (uint8_t *)wmem_alloc0(wmem_file_scope(), length);
2256 if (data) {
2257 memcpy(bn->data, data, length);
2260 bn->length = length;
2261 return bn;
2264 static bool
2265 ssh_read_e(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2267 // store the client's public part (e) for later usage
2268 uint32_t length = tvb_get_ntohl(tvb, offset);
2269 global_data->kex_e = ssh_kex_make_bignum(NULL, length);
2270 if (!global_data->kex_e) {
2271 return false;
2273 tvb_memcpy(tvb, global_data->kex_e->data, offset + 4, length);
2274 return true;
2277 static bool
2278 ssh_read_f(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2280 // store the server's public part (f) for later usage
2281 uint32_t length = tvb_get_ntohl(tvb, offset);
2282 global_data->kex_f = ssh_kex_make_bignum(NULL, length);
2283 if (!global_data->kex_f) {
2284 return false;
2286 tvb_memcpy(tvb, global_data->kex_f->data, offset + 4, length);
2287 return true;
2290 static ssh_bignum *
2291 ssh_read_mpint(tvbuff_t *tvb, int offset)
2293 // store the DH group modulo (p) for later usage
2294 int length = tvb_get_ntohl(tvb, offset);
2295 ssh_bignum * bn = ssh_kex_make_bignum(NULL, length);
2296 if (!bn) {
2297 ws_debug("invalid bignum length %u", length);
2298 return NULL;
2300 tvb_memcpy(tvb, bn->data, offset + 4, length);
2301 return bn;
2304 static void
2305 ssh_keylog_hash_write_secret(struct ssh_flow_data *global_data)
2308 * This computation is defined differently for each key exchange method:
2309 * https://tools.ietf.org/html/rfc4253#page-23
2310 * https://tools.ietf.org/html/rfc5656#page-8
2311 * https://tools.ietf.org/html/rfc4419#page-4
2312 * All key exchange methods:
2313 * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16
2316 gcry_md_hd_t hd;
2317 ssh_key_map_entry_t *entry;
2318 ssh_bignum *secret = NULL;
2319 int length;
2320 bool client_cookie = false;
2322 ssh_keylog_read_file();
2324 unsigned kex_type = ssh_kex_type(global_data->kex);
2325 unsigned kex_hash_type = ssh_kex_hash_type(global_data->kex);
2327 entry = (ssh_key_map_entry_t *)g_hash_table_lookup(ssh_master_key_map, global_data->peer_data[SERVER_PEER_DATA].bn_cookie);
2328 if (!entry) {
2329 entry = (ssh_key_map_entry_t *)g_hash_table_lookup(ssh_master_key_map, global_data->peer_data[CLIENT_PEER_DATA].bn_cookie);
2330 client_cookie = true;
2332 if (!entry) {
2333 ws_debug("ssh decryption: no entry in keylog file for this session");
2334 global_data->do_decrypt = false;
2335 return;
2338 if (!strcmp(entry->type, "PRIVATE_KEY")) {
2339 if (client_cookie) {
2340 secret = ssh_kex_shared_secret(kex_type, global_data->kex_f, entry->key_material, global_data->kex_gex_p);
2341 } else {
2342 secret = ssh_kex_shared_secret(kex_type, global_data->kex_e, entry->key_material, global_data->kex_gex_p);
2344 } else if (!strcmp(entry->type, "SHARED_SECRET")) {
2345 secret = ssh_kex_make_bignum(entry->key_material->data, entry->key_material->length);
2346 } else {
2347 ws_debug("ssh decryption: unknown key type in keylog file");
2348 global_data->do_decrypt = false;
2349 return;
2352 if (!secret) {
2353 ws_debug("ssh decryption: no key material for this session");
2354 global_data->do_decrypt = false;
2355 return;
2358 // shared secret data needs to be written as an mpint, and we need it later
2359 if (secret->data[0] & 0x80) { // Stored in Big endian
2360 length = secret->length + 1;
2361 char *tmp = (char *)wmem_alloc0(wmem_packet_scope(), length);
2362 memcpy(tmp + 1, secret->data, secret->length);
2363 tmp[0] = 0;
2364 secret->data = tmp;
2365 secret->length = length;
2367 ssh_hash_buffer_put_string(global_data->kex_shared_secret, secret->data, secret->length);
2369 wmem_array_t * kex_gex_p = wmem_array_new(wmem_packet_scope(), 1);
2370 if(global_data->kex_gex_p){ssh_hash_buffer_put_string(kex_gex_p, global_data->kex_gex_p->data, global_data->kex_gex_p->length);}
2371 wmem_array_t * kex_gex_g = wmem_array_new(wmem_packet_scope(), 1);
2372 if(global_data->kex_gex_g){ssh_hash_buffer_put_string(kex_gex_g, global_data->kex_gex_g->data, global_data->kex_gex_g->length);}
2373 wmem_array_t * kex_e = wmem_array_new(wmem_packet_scope(), 1);
2374 if(global_data->kex_e){ssh_hash_buffer_put_string(kex_e, global_data->kex_e->data, global_data->kex_e->length);}
2375 wmem_array_t * kex_f = wmem_array_new(wmem_packet_scope(), 1);
2376 if(global_data->kex_f){ssh_hash_buffer_put_string(kex_f, global_data->kex_f->data, global_data->kex_f->length);}
2378 wmem_array_t * kex_hash_buffer = wmem_array_new(wmem_packet_scope(), 1);
2379 ssh_print_data("client_version", (const unsigned char *)wmem_array_get_raw(global_data->kex_client_version), wmem_array_get_count(global_data->kex_client_version));
2380 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_client_version), wmem_array_get_count(global_data->kex_client_version));
2381 ssh_print_data("server_version", (const unsigned char *)wmem_array_get_raw(global_data->kex_server_version), wmem_array_get_count(global_data->kex_server_version));
2382 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_version), wmem_array_get_count(global_data->kex_server_version));
2383 ssh_print_data("client_key_exchange_init", (const unsigned char *)wmem_array_get_raw(global_data->kex_client_key_exchange_init), wmem_array_get_count(global_data->kex_client_key_exchange_init));
2384 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_client_key_exchange_init), wmem_array_get_count(global_data->kex_client_key_exchange_init));
2385 ssh_print_data("server_key_exchange_init", (const unsigned char *)wmem_array_get_raw(global_data->kex_server_key_exchange_init), wmem_array_get_count(global_data->kex_server_key_exchange_init));
2386 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_key_exchange_init), wmem_array_get_count(global_data->kex_server_key_exchange_init));
2387 ssh_print_data("kex_server_host_key_blob", (const unsigned char *)wmem_array_get_raw(global_data->kex_server_host_key_blob), wmem_array_get_count(global_data->kex_server_host_key_blob));
2388 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_host_key_blob), wmem_array_get_count(global_data->kex_server_host_key_blob));
2389 if(kex_type==SSH_KEX_DH_GEX){
2390 ssh_print_data("kex_gex_bits_min", (const unsigned char *)wmem_array_get_raw(global_data->kex_gex_bits_min), wmem_array_get_count(global_data->kex_gex_bits_min));
2391 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_gex_bits_min), wmem_array_get_count(global_data->kex_gex_bits_min));
2392 ssh_print_data("kex_gex_bits_req", (const unsigned char *)wmem_array_get_raw(global_data->kex_gex_bits_req), wmem_array_get_count(global_data->kex_gex_bits_req));
2393 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_gex_bits_req), wmem_array_get_count(global_data->kex_gex_bits_req));
2394 ssh_print_data("kex_gex_bits_max", (const unsigned char *)wmem_array_get_raw(global_data->kex_gex_bits_max), wmem_array_get_count(global_data->kex_gex_bits_max));
2395 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_gex_bits_max), wmem_array_get_count(global_data->kex_gex_bits_max));
2396 ssh_print_data("key modulo (p)", (const unsigned char *)wmem_array_get_raw(kex_gex_p), wmem_array_get_count(kex_gex_p));
2397 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_gex_p), wmem_array_get_count(kex_gex_p));
2398 ssh_print_data("key base (g)", (const unsigned char *)wmem_array_get_raw(kex_gex_g), wmem_array_get_count(kex_gex_g));
2399 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_gex_g), wmem_array_get_count(kex_gex_g));
2400 ssh_print_data("key client (e)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
2401 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
2402 ssh_print_data("key server (f)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
2403 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
2405 if(kex_type==SSH_KEX_DH_GROUP1 || kex_type==SSH_KEX_DH_GROUP14 || kex_type==SSH_KEX_DH_GROUP16 || kex_type==SSH_KEX_DH_GROUP18){
2406 ssh_print_data("key client (e)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
2407 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
2408 ssh_print_data("key server (f)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
2409 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
2411 if(kex_type==SSH_KEX_CURVE25519){
2412 ssh_print_data("key client (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
2413 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
2414 ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
2415 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
2417 ssh_print_data("shared secret", (const unsigned char *)wmem_array_get_raw(global_data->kex_shared_secret), wmem_array_get_count(global_data->kex_shared_secret));
2418 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_shared_secret), wmem_array_get_count(global_data->kex_shared_secret));
2420 ssh_print_data("exchange", (const unsigned char *)wmem_array_get_raw(kex_hash_buffer), wmem_array_get_count(kex_hash_buffer));
2422 unsigned hash_len = 32;
2423 if(kex_hash_type==SSH_KEX_HASH_SHA1) {
2424 gcry_md_open(&hd, GCRY_MD_SHA1, 0);
2425 hash_len = 20;
2426 } else if(kex_hash_type==SSH_KEX_HASH_SHA256) {
2427 gcry_md_open(&hd, GCRY_MD_SHA256, 0);
2428 hash_len = 32;
2429 } else if(kex_hash_type==SSH_KEX_HASH_SHA512) {
2430 gcry_md_open(&hd, GCRY_MD_SHA512, 0);
2431 hash_len = 64;
2432 } else {
2433 ws_debug("kex_hash_type type %d not supported", kex_hash_type);
2434 return;
2436 char *exchange_hash = (char *)wmem_alloc0(wmem_file_scope(), hash_len);
2437 gcry_md_write(hd, wmem_array_get_raw(kex_hash_buffer), wmem_array_get_count(kex_hash_buffer));
2438 memcpy(exchange_hash, gcry_md_read(hd, 0), hash_len);
2439 gcry_md_close(hd);
2440 ssh_print_data("hash", exchange_hash, hash_len);
2441 global_data->secret = secret;
2442 ssh_derive_symmetric_keys(secret, exchange_hash, hash_len, global_data);
2445 // the purpose of this function is to deal with all different kex methods
2446 static ssh_bignum *
2447 ssh_kex_shared_secret(int kex_type, ssh_bignum *pub, ssh_bignum *priv, ssh_bignum *modulo)
2449 DISSECTOR_ASSERT(pub != NULL);
2450 DISSECTOR_ASSERT(priv != NULL);
2452 ssh_bignum *secret = ssh_kex_make_bignum(NULL, pub->length);
2453 if (!secret) {
2454 ws_debug("invalid key length %u", pub->length);
2455 return NULL;
2458 if(kex_type==SSH_KEX_DH_GEX){
2459 gcry_mpi_t b = NULL;
2460 gcry_mpi_scan(&b, GCRYMPI_FMT_USG, pub->data, pub->length, NULL);
2461 gcry_mpi_t d = NULL, e = NULL, m = NULL;
2462 size_t result_len = 0;
2463 d = gcry_mpi_new(pub->length*8);
2464 gcry_mpi_scan(&e, GCRYMPI_FMT_USG, priv->data, priv->length, NULL);
2465 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, modulo->data, modulo->length, NULL);
2466 gcry_mpi_powm(d, b, e, m); // gcry_mpi_powm(d, b, e, m) => d = b^e % m
2467 gcry_mpi_print(GCRYMPI_FMT_USG, secret->data, secret->length, &result_len, d);
2468 secret->length = (unsigned)result_len; // Should not be larger than what fits in a 32-bit unsigned integer...
2469 gcry_mpi_release(d);
2470 gcry_mpi_release(b);
2471 gcry_mpi_release(e);
2472 gcry_mpi_release(m);
2474 }else if(kex_type==SSH_KEX_DH_GROUP1 || kex_type==SSH_KEX_DH_GROUP14 || kex_type==SSH_KEX_DH_GROUP16 || kex_type==SSH_KEX_DH_GROUP18){
2475 gcry_mpi_t m = NULL;
2476 if(kex_type==SSH_KEX_DH_GROUP1){
2477 static const uint8_t p[] = {
2478 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
2479 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
2480 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
2481 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
2482 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
2483 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
2484 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
2485 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
2486 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
2487 }else if(kex_type==SSH_KEX_DH_GROUP14){
2488 //p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
2489 static const uint8_t p[] = {
2490 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
2491 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
2492 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
2493 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
2494 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
2495 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
2496 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
2497 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
2498 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
2499 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
2500 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
2501 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
2502 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
2503 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
2504 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
2505 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2506 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
2507 }else if(kex_type==SSH_KEX_DH_GROUP16){
2508 //p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF
2509 static const uint8_t p[] = {
2510 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
2511 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
2512 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
2513 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
2514 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
2515 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
2516 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
2517 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
2518 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
2519 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
2520 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
2521 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
2522 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
2523 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
2524 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
2525 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
2526 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
2527 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
2528 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
2529 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
2530 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
2531 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
2532 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
2533 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
2534 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
2535 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
2536 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
2537 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
2538 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
2539 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
2540 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
2541 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
2542 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
2543 }else if(kex_type==SSH_KEX_DH_GROUP18){
2544 //p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF
2545 static const uint8_t p[] = {
2546 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
2547 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
2548 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
2549 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
2550 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
2551 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
2552 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
2553 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
2554 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
2555 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
2556 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
2557 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
2558 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
2559 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
2560 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
2561 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
2562 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
2563 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
2564 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
2565 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
2566 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
2567 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
2568 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
2569 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
2570 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
2571 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
2572 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
2573 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
2574 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
2575 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
2576 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
2577 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
2578 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
2579 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
2580 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
2581 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
2582 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
2583 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
2584 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
2585 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
2586 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
2587 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
2588 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
2589 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
2590 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
2591 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
2592 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
2593 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
2594 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
2595 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
2596 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
2597 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
2598 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
2599 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
2600 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
2601 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
2602 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
2603 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
2604 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
2605 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
2606 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
2607 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
2608 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
2609 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
2610 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
2613 gcry_mpi_t b = NULL;
2614 gcry_mpi_scan(&b, GCRYMPI_FMT_USG, pub->data, pub->length, NULL);
2615 gcry_mpi_t d = NULL, e = NULL;
2616 size_t result_len = 0;
2617 d = gcry_mpi_new(pub->length*8);
2618 gcry_mpi_scan(&e, GCRYMPI_FMT_USG, priv->data, priv->length, NULL);
2619 gcry_mpi_powm(d, b, e, m); // gcry_mpi_powm(d, b, e, m) => d = b^e % m
2620 gcry_mpi_print(GCRYMPI_FMT_USG, secret->data, secret->length, &result_len, d);
2621 secret->length = (unsigned)result_len; // Should not be larger than what fits in a 32-bit unsigned integer...
2622 gcry_mpi_release(d);
2623 gcry_mpi_release(b);
2624 gcry_mpi_release(e);
2625 gcry_mpi_release(m);
2626 }else if(kex_type==SSH_KEX_CURVE25519){
2627 if (crypto_scalarmult_curve25519(secret->data, priv->data, pub->data)) {
2628 ws_debug("curve25519: can't compute shared secret");
2629 return NULL;
2631 } else {
2632 ws_debug("kex_type type %d not supported", kex_type);
2633 return 0;
2636 return secret;
2639 static char *
2640 ssh_string(const char *string, unsigned length)
2642 char *ssh_string = (char *)wmem_alloc(wmem_packet_scope(), length + 4);
2643 ssh_string[0] = (length >> 24) & 0xff;
2644 ssh_string[1] = (length >> 16) & 0xff;
2645 ssh_string[2] = (length >> 8) & 0xff;
2646 ssh_string[3] = length & 0xff;
2647 memcpy(ssh_string + 4, string, length);
2648 return ssh_string;
2651 static void
2652 ssh_hash_buffer_put_string(wmem_array_t *buffer, const char *string,
2653 unsigned length)
2655 if (!buffer) {
2656 return;
2659 char *string_with_length = ssh_string(string, length);
2660 wmem_array_append(buffer, string_with_length, length + 4);
2663 static void
2664 ssh_hash_buffer_put_uint32(wmem_array_t *buffer, unsigned val)
2666 if (!buffer) {
2667 return;
2670 char buf[4];
2671 buf[0] = (val >> 24); buf[1] = (val >> 16); buf[2] = (val >> 8); buf[3] = (val >> 0);
2672 wmem_array_append(buffer, buf, 4);
2675 static void ssh_derive_symmetric_keys(ssh_bignum *secret, char *exchange_hash,
2676 unsigned hash_length, struct ssh_flow_data *global_data)
2678 if (!global_data->session_id) {
2679 global_data->session_id = exchange_hash;
2680 global_data->session_id_length = hash_length;
2683 unsigned int we_need = 0;
2684 for(int peer_cnt=0;peer_cnt<2;peer_cnt++){
2685 struct ssh_peer_data * peer_data = &global_data->peer_data[peer_cnt];
2686 // required size of key depends on cipher used. chacha20 wants 64 bytes
2687 unsigned need = 0;
2688 if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
2689 need = 64;
2690 } else if (CIPHER_AES128_CBC == peer_data->cipher_id || CIPHER_AES128_CTR == peer_data->cipher_id || CIPHER_AES128_GCM == peer_data->cipher_id) {
2691 need = 16;
2692 } else if (CIPHER_AES192_CBC == peer_data->cipher_id || CIPHER_AES192_CTR == peer_data->cipher_id) {
2693 need = 24;
2694 } else if (CIPHER_AES256_CBC == peer_data->cipher_id || CIPHER_AES256_CTR == peer_data->cipher_id || CIPHER_AES256_GCM == peer_data->cipher_id) {
2695 need = 32;
2696 } else {
2697 ssh_debug_printf("ssh: cipher (%d) is unknown or not set\n", peer_data->cipher_id);
2698 ssh_debug_flush();
2700 if(peer_data->mac_id == CIPHER_MAC_SHA2_256){
2701 need = 32;
2702 }else{
2703 ssh_debug_printf("ssh: MAC (%d) is unknown or not set\n", peer_data->mac_id);
2704 ssh_debug_flush();
2706 if (we_need<need) {
2707 we_need = need;
2711 for (int i = 0; i < 6; i ++) {
2712 ssh_derive_symmetric_key(secret, exchange_hash, hash_length,
2713 'A' + i, &global_data->new_keys[i], global_data, we_need);
2714 if(i==0){ ssh_print_data("Initial IV client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
2715 }else if(i==1){ ssh_print_data("Initial IV server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
2716 }else if(i==2){ ssh_print_data("Encryption key client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
2717 }else if(i==3){ ssh_print_data("Encryption key server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
2718 }else if(i==4){ ssh_print_data("Integrity key client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
2719 }else if(i==5){ ssh_print_data("Integrity key server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
2724 static void ssh_derive_symmetric_key(ssh_bignum *secret, char *exchange_hash,
2725 unsigned hash_length, char id, ssh_bignum *result_key,
2726 struct ssh_flow_data *global_data, unsigned we_need)
2728 gcry_md_hd_t hd;
2730 unsigned kex_hash_type = ssh_kex_hash_type(global_data->kex);
2731 int algo = GCRY_MD_SHA256;
2732 if(kex_hash_type==SSH_KEX_HASH_SHA1){
2733 algo = GCRY_MD_SHA1;
2734 }else if(kex_hash_type==SSH_KEX_HASH_SHA256){
2735 algo = GCRY_MD_SHA256;
2736 }else if(kex_hash_type==SSH_KEX_HASH_SHA512){
2737 algo = GCRY_MD_SHA512;
2739 unsigned len = gcry_md_get_algo_dlen(algo);
2741 result_key->data = (unsigned char *)wmem_alloc(wmem_file_scope(), we_need);
2743 char *secret_with_length = ssh_string(secret->data, secret->length);
2745 if (gcry_md_open(&hd, algo, 0) == 0) {
2746 gcry_md_write(hd, secret_with_length, secret->length + 4);
2747 gcry_md_write(hd, exchange_hash, hash_length);
2748 gcry_md_putc(hd, id);
2749 gcry_md_write(hd, global_data->session_id, hash_length);
2750 unsigned add_length = MIN(len, we_need);
2751 memcpy(result_key->data, gcry_md_read(hd, 0), add_length);
2752 gcry_md_close(hd);
2755 // expand key
2756 for (unsigned have = len; have < we_need; have += len) {
2757 if (gcry_md_open(&hd, algo, 0) == 0) {
2758 gcry_md_write(hd, secret_with_length, secret->length + 4);
2759 gcry_md_write(hd, exchange_hash, hash_length);
2760 gcry_md_write(hd, result_key->data+have-len, len);
2761 unsigned add_length = MIN(len, we_need - have);
2762 memcpy(result_key->data+have, gcry_md_read(hd, 0), add_length);
2763 gcry_md_close(hd);
2767 result_key->length = we_need;
2770 static void
2771 ssh_choose_enc_mac(struct ssh_flow_data *global_data)
2773 for(int peer_cnt=0;peer_cnt<2;peer_cnt++){
2774 struct ssh_peer_data * peer_data = &global_data->peer_data[peer_cnt];
2775 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[peer_cnt],
2776 global_data->peer_data[SERVER_PEER_DATA].enc_proposals[peer_cnt],
2777 &peer_data->enc);
2778 /* some ciphers have their own MAC so the "negotiated" one is meaningless */
2779 if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
2780 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
2781 peer_data->mac = wmem_strdup(wmem_file_scope(), (const char *)"<implicit>");
2782 peer_data->mac_length = 16;
2783 peer_data->length_is_plaintext = 1;
2785 else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
2786 peer_data->mac = wmem_strdup(wmem_file_scope(), (const char *)"<implicit>");
2787 peer_data->mac_length = 16;
2789 else {
2790 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[peer_cnt],
2791 global_data->peer_data[SERVER_PEER_DATA].mac_proposals[peer_cnt],
2792 &peer_data->mac);
2793 ssh_set_mac_length(peer_data);
2795 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[peer_cnt],
2796 global_data->peer_data[SERVER_PEER_DATA].comp_proposals[peer_cnt],
2797 &peer_data->comp);
2800 ssh_decryption_set_cipher_id(&global_data->peer_data[CLIENT_PEER_DATA]);
2801 ssh_decryption_set_mac_id(&global_data->peer_data[CLIENT_PEER_DATA]);
2802 ssh_decryption_set_cipher_id(&global_data->peer_data[SERVER_PEER_DATA]);
2803 ssh_decryption_set_mac_id(&global_data->peer_data[SERVER_PEER_DATA]);
2806 static void
2807 ssh_decryption_set_cipher_id(struct ssh_peer_data *peer)
2809 char *cipher_name = peer->enc;
2811 if (!cipher_name) {
2812 peer->cipher = NULL;
2813 ws_debug("ERROR: cipher_name is NULL");
2814 } else if (0 == strcmp(cipher_name, "chacha20-poly1305@openssh.com")) {
2815 peer->cipher_id = GCRY_CIPHER_CHACHA20;
2816 } else if (0 == strcmp(cipher_name, "aes128-gcm@openssh.com")) {
2817 peer->cipher_id = CIPHER_AES128_GCM;
2818 } else if (0 == strcmp(cipher_name, "aes128-gcm")) {
2819 peer->cipher_id = CIPHER_AES128_GCM;
2820 } else if (0 == strcmp(cipher_name, "aes256-gcm@openssh.com")) {
2821 peer->cipher_id = CIPHER_AES256_GCM;
2822 } else if (0 == strcmp(cipher_name, "aes256-gcm")) {
2823 peer->cipher_id = CIPHER_AES256_GCM;
2824 } else if (0 == strcmp(cipher_name, "aes128-cbc")) {
2825 peer->cipher_id = CIPHER_AES128_CBC;
2826 } else if (0 == strcmp(cipher_name, "aes192-cbc")) {
2827 peer->cipher_id = CIPHER_AES192_CBC;
2828 } else if (0 == strcmp(cipher_name, "aes256-cbc")) {
2829 peer->cipher_id = CIPHER_AES256_CBC;
2830 } else if (0 == strcmp(cipher_name, "aes128-ctr")) {
2831 peer->cipher_id = CIPHER_AES128_CTR;
2832 } else if (0 == strcmp(cipher_name, "aes192-ctr")) {
2833 peer->cipher_id = CIPHER_AES192_CTR;
2834 } else if (0 == strcmp(cipher_name, "aes256-ctr")) {
2835 peer->cipher_id = CIPHER_AES256_CTR;
2836 } else {
2837 peer->cipher = NULL;
2838 ws_debug("decryption not supported: %s", cipher_name);
2842 static void
2843 ssh_decryption_set_mac_id(struct ssh_peer_data *peer)
2845 char *mac_name = peer->mac;
2847 if (!mac_name) {
2848 peer->mac = NULL;
2849 ws_debug("ERROR: mac_name is NULL");
2850 } else if (0 == strcmp(mac_name, "hmac-sha2-256")) {
2851 peer->mac_id = CIPHER_MAC_SHA2_256;
2852 } else {
2853 ws_debug("decryption MAC not supported: %s", mac_name);
2857 static bool
2858 gcry_cipher_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data)
2860 gcry_cipher_hd_t hd = (gcry_cipher_hd_t)user_data;
2862 gcry_cipher_close(hd);
2864 return false;
2867 static void
2868 ssh_decryption_setup_cipher(struct ssh_peer_data *peer_data,
2869 ssh_bignum *iv, ssh_bignum *key)
2871 gcry_error_t err;
2872 gcry_cipher_hd_t *hd1, *hd2;
2874 hd1 = &peer_data->cipher;
2875 hd2 = &peer_data->cipher_2;
2877 if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
2878 if (gcry_cipher_open(hd1, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM, 0) ||
2879 gcry_cipher_open(hd2, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM, 0)) {
2880 gcry_cipher_close(*hd1);
2881 gcry_cipher_close(*hd2);
2882 ws_debug("ssh: can't open chacha20 cipher handles");
2883 return;
2886 char k1[32];
2887 char k2[32];
2888 if(key->data){
2889 memcpy(k1, key->data, 32);
2890 memcpy(k2, key->data + 32, 32);
2891 }else{
2892 memset(k1, 0, 32);
2893 memset(k2, 0, 32);
2896 ssh_debug_printf("ssh: cipher is chacha20\n");
2897 ssh_print_data("key 1", k1, 32);
2898 ssh_print_data("key 2", k2, 32);
2900 if ((err = gcry_cipher_setkey(*hd1, k1, 32))) {
2901 gcry_cipher_close(*hd1);
2902 ws_debug("ssh: can't set chacha20 cipher key %s", gcry_strerror(err));
2903 return;
2906 if ((err = gcry_cipher_setkey(*hd2, k2, 32))) {
2907 gcry_cipher_close(*hd1);
2908 gcry_cipher_close(*hd2);
2909 ws_debug("ssh: can't set chacha20 cipher key %s", gcry_strerror(err));
2910 return;
2913 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
2914 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd2);
2916 } else if (CIPHER_AES128_CBC == peer_data->cipher_id || CIPHER_AES192_CBC == peer_data->cipher_id || CIPHER_AES256_CBC == peer_data->cipher_id) {
2917 int iKeyLen = CIPHER_AES128_CBC == peer_data->cipher_id?16:CIPHER_AES192_CBC == peer_data->cipher_id?24:32;
2918 if (gcry_cipher_open(hd1, CIPHER_AES128_CBC == peer_data->cipher_id?GCRY_CIPHER_AES128:CIPHER_AES192_CBC == peer_data->cipher_id?GCRY_CIPHER_AES192:GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0)) {
2919 gcry_cipher_close(*hd1);
2920 ws_debug("ssh: can't open aes%d cipher handle", iKeyLen*8);
2921 return;
2923 char k1[32], iv1[16];
2924 if(key->data){
2925 memcpy(k1, key->data, iKeyLen);
2926 }else{
2927 memset(k1, 0, iKeyLen);
2929 if(iv->data){
2930 memcpy(iv1, iv->data, 16);
2931 }else{
2932 memset(iv1, 0, 16);
2935 ssh_debug_printf("ssh: cipher is aes%d-cbc\n", iKeyLen*8);
2936 ssh_print_data("key", k1, iKeyLen);
2937 ssh_print_data("iv", iv1, 16);
2939 if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
2940 gcry_cipher_close(*hd1);
2941 ws_debug("ssh: can't set aes%d cipher key", iKeyLen*8);
2942 ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
2943 return;
2946 if ((err = gcry_cipher_setiv(*hd1, iv1, 16))) {
2947 gcry_cipher_close(*hd1);
2948 ws_debug("ssh: can't set aes%d cipher iv", iKeyLen*8);
2949 ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
2950 return;
2953 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
2955 } else if (CIPHER_AES128_CTR == peer_data->cipher_id || CIPHER_AES192_CTR == peer_data->cipher_id || CIPHER_AES256_CTR == peer_data->cipher_id) {
2956 int iKeyLen = CIPHER_AES128_CTR == peer_data->cipher_id?16:CIPHER_AES192_CTR == peer_data->cipher_id?24:32;
2957 if (gcry_cipher_open(hd1, CIPHER_AES128_CTR == peer_data->cipher_id?GCRY_CIPHER_AES128:CIPHER_AES192_CTR == peer_data->cipher_id?GCRY_CIPHER_AES192:GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR, 0)) {
2958 gcry_cipher_close(*hd1);
2959 ws_debug("ssh: can't open aes%d cipher handle", iKeyLen*8);
2960 return;
2962 char k1[32], iv1[16];
2963 if(key->data){
2964 memcpy(k1, key->data, iKeyLen);
2965 }else{
2966 memset(k1, 0, iKeyLen);
2968 if(iv->data){
2969 memcpy(iv1, iv->data, 16);
2970 }else{
2971 memset(iv1, 0, 16);
2974 ssh_debug_printf("ssh: cipher is aes%d-ctr\n", iKeyLen*8);
2975 ssh_print_data("key", k1, iKeyLen);
2976 ssh_print_data("iv", iv1, 16);
2978 if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
2979 gcry_cipher_close(*hd1);
2980 ws_debug("ssh: can't set aes%d cipher key", iKeyLen*8);
2981 ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
2982 return;
2985 if ((err = gcry_cipher_setctr(*hd1, iv1, 16))) {
2986 gcry_cipher_close(*hd1);
2987 ws_debug("ssh: can't set aes%d cipher iv", iKeyLen*8);
2988 ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
2989 return;
2992 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
2994 } else if (CIPHER_AES128_GCM == peer_data->cipher_id || CIPHER_AES256_GCM == peer_data->cipher_id) {
2995 int iKeyLen = CIPHER_AES128_GCM == peer_data->cipher_id?16:32;
2996 if (gcry_cipher_open(hd1, CIPHER_AES128_GCM == peer_data->cipher_id?GCRY_CIPHER_AES128:GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0)) {
2997 gcry_cipher_close(*hd1);
2998 ws_debug("ssh: can't open aes%d cipher handle", iKeyLen*8);
2999 return;
3002 char k1[32], iv2[12];
3003 if(key->data){
3004 memcpy(k1, key->data, iKeyLen);
3005 }else{
3006 memset(k1, 0, iKeyLen);
3008 if(iv->data){
3009 memcpy(peer_data->iv, iv->data, 12);
3010 }else{
3011 memset(iv2, 0, 12);
3014 ssh_debug_printf("ssh: cipher is aes%d-gcm\n", iKeyLen*8);
3015 ssh_print_data("key", k1, iKeyLen);
3016 ssh_print_data("iv", peer_data->iv, 12);
3018 if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3019 gcry_cipher_close(*hd1);
3020 ws_debug("ssh: can't set aes%d cipher key", iKeyLen*8);
3021 ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3022 return;
3025 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3027 } else {
3028 ssh_debug_printf("ssh: cipher (%d) is unknown or not set\n", peer_data->cipher_id);
3032 static void
3033 ssh_decryption_setup_mac(struct ssh_peer_data *peer_data,
3034 ssh_bignum *iv)
3036 if(peer_data->mac_id == CIPHER_MAC_SHA2_256){
3037 if(iv->data){
3038 memcpy(peer_data->hmac_iv, iv->data, 32);
3039 }else{
3040 memset(peer_data->hmac_iv, 0, 32);
3042 peer_data->hmac_iv_len = 32;
3043 ssh_debug_printf("ssh: mac is hmac-sha2-256\n");
3044 ssh_print_data("iv", peer_data->hmac_iv, peer_data->hmac_iv_len);
3045 }else{
3046 ws_debug("ssh: unsupported MAC");
3050 /* libgcrypt wrappers for HMAC/message digest operations {{{ */
3051 /* hmac abstraction layer */
3052 #define SSH_HMAC gcry_md_hd_t
3054 static inline int
3055 ssh_hmac_init(SSH_HMAC* md, const void * key, int len, int algo)
3057 gcry_error_t err;
3058 const char *err_str, *err_src;
3060 err = gcry_md_open(md,algo, GCRY_MD_FLAG_HMAC);
3061 if (err != 0) {
3062 err_str = gcry_strerror(err);
3063 err_src = gcry_strsource(err);
3064 ssh_debug_printf("ssh_hmac_init(): gcry_md_open failed %s/%s", err_str, err_src);
3065 return -1;
3067 err = gcry_md_setkey(*(md), key, len);
3068 if (err != 0) {
3069 err_str = gcry_strerror(err);
3070 err_src = gcry_strsource(err);
3071 ssh_debug_printf("ssh_hmac_init(): gcry_md_setkey(..., ..., %d) failed %s/%s", len, err_str, err_src);
3072 return -1;
3074 return 0;
3077 static inline void
3078 ssh_hmac_update(SSH_HMAC* md, const void* data, int len)
3080 gcry_md_write(*(md), data, len);
3083 static inline void
3084 ssh_hmac_final(SSH_HMAC* md, unsigned char* data, unsigned* datalen)
3086 int algo;
3087 unsigned len;
3089 algo = gcry_md_get_algo (*(md));
3090 len = gcry_md_get_algo_dlen(algo);
3091 DISSECTOR_ASSERT(len <= *datalen);
3092 memcpy(data, gcry_md_read(*(md), algo), len);
3093 *datalen = len;
3096 static inline void
3097 ssh_hmac_cleanup(SSH_HMAC* md)
3099 gcry_md_close(*(md));
3101 /* libgcrypt wrappers for HMAC/message digest operations }}} */
3103 /* Decryption integrity check {{{ */
3105 static int
3106 ssh_get_digest_by_id(unsigned mac_id)
3108 if(mac_id==CIPHER_MAC_SHA2_256){
3109 return GCRY_MD_SHA256;
3111 return -1;
3114 static void
3115 ssh_calc_mac(struct ssh_peer_data *peer_data, uint32_t seqnr, uint8_t* data, uint32_t datalen, uint8_t* calc_mac)
3117 SSH_HMAC hm;
3118 int md;
3119 uint32_t len;
3120 uint8_t buf[DIGEST_MAX_SIZE];
3122 md=ssh_get_digest_by_id(peer_data->mac_id);
3123 // ssl_debug_printf("ssh_check_mac mac type:%s md %d\n",
3124 // ssl_cipher_suite_dig(decoder->cipher_suite)->name, md);
3126 memset(calc_mac, 0, DIGEST_MAX_SIZE);
3128 if (ssh_hmac_init(&hm, peer_data->hmac_iv, peer_data->hmac_iv_len,md) != 0)
3129 return;
3131 /* hash sequence number */
3132 phton32(buf, seqnr);
3134 ssh_print_data("Mac IV", peer_data->hmac_iv, peer_data->hmac_iv_len);
3135 ssh_print_data("Mac seq", buf, 4);
3136 ssh_print_data("Mac data", data, datalen);
3138 ssh_hmac_update(&hm,buf,4);
3140 ssh_hmac_update(&hm,data,datalen);
3142 /* get digest and digest len*/
3143 len = sizeof(buf);
3144 ssh_hmac_final(&hm,buf,&len);
3145 ssh_hmac_cleanup(&hm);
3146 ssh_print_data("Mac", buf, len);
3147 memcpy(calc_mac, buf, len);
3149 return;
3151 /* Decryption integrity check }}} */
3153 static void
3154 ssh_increment_message_number(packet_info *pinfo, struct ssh_flow_data *global_data,
3155 bool is_response)
3157 if (!PINFO_FD_VISITED(pinfo)) {
3158 ssh_packet_info_t * packet = (ssh_packet_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0);
3159 if(!packet){
3160 packet = wmem_new0(wmem_file_scope(), ssh_packet_info_t);
3161 packet->from_server = is_response;
3162 packet->messages = NULL;
3163 p_add_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0, packet);
3165 (void)global_data;
3169 static unsigned
3170 ssh_decrypt_packet(tvbuff_t *tvb, packet_info *pinfo,
3171 struct ssh_peer_data *peer_data, int offset)
3173 bool is_response = (pinfo->destport != pinfo->match_uint);
3175 gcry_error_t err;
3176 unsigned message_length = 0, seqnr;
3177 char *plain = NULL, *mac;
3178 unsigned mac_len, data_len = 0;
3179 uint8_t calc_mac[DIGEST_MAX_SIZE];
3180 memset(calc_mac, 0, DIGEST_MAX_SIZE);
3182 mac_len = peer_data->mac_length;
3183 seqnr = peer_data->sequence_number;
3185 if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3186 const char *ctext = (const char *)tvb_get_ptr(tvb, offset, 4);
3187 uint8_t plain_length_buf[4];
3189 if (!ssh_decrypt_chacha20(peer_data->cipher_2, seqnr, 0, ctext, 4,
3190 plain_length_buf, 4)) {
3191 ws_debug("ERROR: could not decrypt packet len");
3192 return tvb_captured_length(tvb);
3195 message_length = pntoh32(plain_length_buf);
3197 ssh_debug_printf("chachapoly_crypt seqnr=%d [%u]\n", seqnr, message_length);
3199 ssh_debug_printf("%s plain for seq = %d len = %u\n", is_response?"s2c":"c2s", seqnr, message_length);
3200 if(message_length>32768){
3201 ws_debug("ssh: unreasonable message length %u", message_length);
3202 return tvb_captured_length(tvb);
3205 plain = (char *)wmem_alloc0(pinfo->pool, message_length+4);
3206 memcpy(plain, plain_length_buf, 4);
3207 const char *ctext2 = (const char *)tvb_get_ptr(tvb, offset+4,
3208 message_length);
3210 if (!ssh_decrypt_chacha20(peer_data->cipher, seqnr, 1, ctext2,
3211 message_length, plain+4, message_length)) {
3212 ws_debug("ERROR: could not decrypt packet payload");
3213 return tvb_captured_length(tvb);
3216 mac = (char *)tvb_get_ptr(tvb, offset + 4 + message_length, mac_len);
3217 char poly_key[32], iv[16];
3219 memset(poly_key, 0, 32);
3220 memset(iv, 0, 8);
3221 phton64(iv+8, (uint64_t)seqnr);
3222 gcry_cipher_setiv(peer_data->cipher, iv, mac_len);
3223 gcry_cipher_encrypt(peer_data->cipher, poly_key, 32, poly_key, 32);
3225 gcry_mac_hd_t mac_hd;
3226 gcry_mac_open(&mac_hd, GCRY_MAC_POLY1305, 0, NULL);
3227 gcry_mac_setkey(mac_hd, poly_key, 32);
3228 gcry_mac_write(mac_hd, ctext, 4);
3229 gcry_mac_write(mac_hd, ctext2, message_length);
3230 if (gcry_mac_verify(mac_hd, mac, mac_len)) {
3231 ws_debug("ssh: MAC does not match");
3233 size_t buflen = DIGEST_MAX_SIZE;
3234 gcry_mac_read(mac_hd, calc_mac, &buflen);
3235 gcry_mac_close(mac_hd);
3237 data_len = message_length + 4;
3239 // ssh_print_data(is_response?"s2c encrypted":"c2s encrypted", ctext2, message_length+4+mac_len);
3240 ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
3241 ssh_print_data("", plain, message_length+4);
3242 } else if (CIPHER_AES128_GCM == peer_data->cipher_id || CIPHER_AES256_GCM == peer_data->cipher_id) {
3244 /* AES GCM for Secure Shell [RFC 5647] */
3245 /* The message length is Additional Authenticated Data */
3246 /* XXX: If there are fewer than 4 octets available, we need to
3247 * ask the TCP dissector for DESEGMENT_ONE_MORE_SEGMENT instead
3248 * of throwing an exception here, if we're desegmenting.
3250 message_length = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
3251 unsigned remaining = tvb_reported_length_remaining(tvb, offset);
3252 ssh_debug_printf("length: %d, remaining: %d\n", message_length, remaining);
3253 /* The minimum size of a packet (not counting mac) is 16. */
3254 if (message_length < 16) {
3255 ws_debug("ssh: unreasonable message length %u", message_length);
3256 return tvb_captured_length(tvb);
3259 /* SSH requires that the data to be encrypted (not including the AAD,
3260 * so message_length) be a multiple of the block size, 16 octets */
3261 if (message_length % 16 != 0) {
3262 ssh_debug_printf("length not a multiple of block length (16)!\n");
3265 /* If tvb_reported_length_remaining(tvb, offset + 4) is less
3266 * than message_length + mac_len, then we should ask the TCP
3267 * dissector for more data if we're desegmenting. That is
3268 * simpler than trying to handle fragmentation ourselves.
3270 const char *ctext = (const char *)tvb_get_ptr(tvb, offset + 4,
3271 message_length);
3272 plain = (char *)wmem_alloc(pinfo->pool, message_length+4);
3273 phton32(plain, message_length);
3275 /* gcry_cipher_setiv(peer_data->cipher, iv, 12); */
3276 if ((err = gcry_cipher_setiv(peer_data->cipher, peer_data->iv, 12))) {
3277 //gcry_cipher_close(peer_data->cipher);
3278 //Don't close this unless we also remove the wmem callback
3279 // TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
3280 #ifndef _WIN32
3281 ws_debug("ssh: can't set aes128 cipher iv");
3282 ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3283 #endif //ndef _WIN32
3284 return tvb_captured_length(tvb);
3286 int idx = 12;
3288 idx -= 1;
3289 peer_data->iv[idx] += 1;
3290 }while(idx>4 && peer_data->iv[idx]==0);
3292 if ((err = gcry_cipher_authenticate(peer_data->cipher, plain, 4))) {
3293 // TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
3294 #ifndef _WIN32
3295 ws_debug("can't authenticate using aes128-gcm: %s\n", gpg_strerror(err));
3296 #endif //ndef _WIN32
3297 return tvb_captured_length(tvb);
3300 if ((err = gcry_cipher_decrypt(peer_data->cipher, plain+4, message_length,
3301 ctext, message_length))) {
3302 // TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
3303 #ifndef _WIN32
3304 ws_debug("can't decrypt aes-gcm %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3306 #endif //ndef _WIN32
3307 return tvb_captured_length(tvb);
3310 if (gcry_cipher_gettag (peer_data->cipher, calc_mac, 16)) {
3311 // TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
3312 #ifndef _WIN32
3313 ws_debug ("aes128-gcm, gcry_cipher_gettag() failed\n");
3314 #endif //ndef _WIN32
3315 return tvb_captured_length(tvb);
3318 if ((err = gcry_cipher_reset(peer_data->cipher))) {
3319 // TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
3320 #ifndef _WIN32
3321 ws_debug("aes-gcm, gcry_cipher_reset failed: %s\n", gpg_strerror (err));
3322 #endif //ndef _WIN32
3323 return tvb_captured_length(tvb);
3326 data_len = message_length + 4;
3328 // ssh_print_data(is_response?"s2c encrypted":"c2s encrypted", ctl, message_length+4+mac_len);
3329 ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
3330 ssh_print_data("", plain, message_length+4);
3332 } else if (CIPHER_AES128_CBC == peer_data->cipher_id || CIPHER_AES128_CTR == peer_data->cipher_id ||
3333 CIPHER_AES192_CBC == peer_data->cipher_id || CIPHER_AES192_CTR == peer_data->cipher_id ||
3334 CIPHER_AES256_CBC == peer_data->cipher_id || CIPHER_AES256_CTR == peer_data->cipher_id) {
3336 message_length = tvb_reported_length_remaining(tvb, offset) - 4 - mac_len;
3338 // TODO: see how to handle fragmentation...
3339 ws_noisy("Getting raw bytes of length %d", tvb_reported_length_remaining(tvb, offset));
3340 /* In CBC and CTR mode, the message length is encrypted as well.
3341 * We need to decrypt one block to get the length.
3342 * If we have fewer than 16 octets, and we're doing desegmentation,
3343 * we should tell the TCP dissector we need ONE_MORE_SEGMENT.
3345 const char *cypher_buf0 = (const char *)tvb_get_ptr(tvb, offset, 16);
3347 char plain0[16];
3348 if (gcry_cipher_decrypt(peer_data->cipher, plain0, 16, cypher_buf0, 16))
3350 ws_debug("can\'t decrypt aes128");
3351 return tvb_captured_length(tvb);
3354 unsigned message_length_decrypted = pntoh32(plain0);
3355 unsigned remaining = tvb_reported_length_remaining(tvb, offset);
3357 /* The message_length value doesn't include the length of the
3358 * message_length field itself, so it must be at least 12 bytes.
3360 if(message_length_decrypted>32768 || message_length_decrypted < 12){
3361 ws_debug("ssh: unreasonable message length %u/%u", message_length_decrypted, message_length);
3362 return tvb_captured_length(tvb);
3365 message_length = message_length_decrypted;
3366 /* SSH requires that the data to be encrypted (message_length+4)
3367 * be a multiple of the block size, 16 octets. */
3368 if (message_length % 16 != 12) {
3369 ssh_debug_printf("total length not a multiple of block length (16)!\n");
3371 plain = (char *)wmem_alloc(pinfo->pool, message_length+4);
3372 memcpy(plain, plain0, 16);
3374 /* If we're desegmenting, we want to test if we have enough
3375 * remaining bytes here. It's easier to have the TCP
3376 * dissector put together a PDU based on our length.
3379 if (message_length - 12 > 0) {
3380 /* All of these functions actually do handle the case where
3381 * there is no data left, so the check is unnecessary.
3383 char *ct = (char *)tvb_get_ptr(tvb, offset + 16, message_length - 12);
3384 if ((err = gcry_cipher_decrypt(peer_data->cipher, plain + 16, message_length - 12, ct, message_length - 12)))
3386 ws_debug("can't decrypt aes-cbc/ctr %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3387 return tvb_captured_length(tvb);
3391 /* XXX: Need to test if we have enough data above if we're
3392 * doing desegmentation; the tvb_get_ptr() calls will throw
3393 * exceptions if there's not enough data before we get here.
3395 if(message_length_decrypted>remaining){
3396 // Need desegmentation
3397 ws_noisy(" need_desegmentation: offset = %d, reported_length_remaining = %d\n",
3398 offset, tvb_reported_length_remaining(tvb, offset));
3399 /* Make data available to ssh_follow_tap_listener */
3400 return tvb_captured_length(tvb);
3403 // ssh_print_data(is_response?"s2c encrypted":"c2s encrypted", ctext, message_length+4+mac_len);
3404 ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
3405 ssh_print_data("", plain, message_length+4);
3407 // TODO: process fragments
3408 data_len = message_length + 4;
3410 ssh_calc_mac(peer_data, seqnr, plain, data_len, calc_mac);
3413 if (mac_len && data_len) {
3414 mac = (char *)tvb_get_ptr(tvb, offset + data_len, mac_len);
3415 if (!memcmp(mac, calc_mac, mac_len)){
3416 ws_noisy("MAC OK");
3417 }else{
3418 ws_debug("MAC ERR");
3419 /* Bad MAC, just show the packet as encrypted. We can get
3420 * this for a known encryption type with no keys currently. */
3421 /* XXX: The TLS dissector has a preference to show the attempt
3422 * anyway if it failed.
3424 return tvb_captured_length(tvb);
3428 if(plain){
3429 // Save message
3431 ssh_packet_info_t *packet = (ssh_packet_info_t *)p_get_proto_data(
3432 wmem_file_scope(), pinfo, proto_ssh, 0);
3433 if(!packet){
3434 packet = wmem_new0(wmem_file_scope(), ssh_packet_info_t);
3435 packet->from_server = is_response;
3436 packet->messages = NULL;
3437 p_add_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0, packet);
3440 int record_id = tvb_raw_offset(tvb)+offset;
3441 ssh_message_info_t *message;
3443 message = wmem_new(wmem_file_scope(), ssh_message_info_t);
3444 message->sequence_number = peer_data->sequence_number++;
3445 message->plain_data = wmem_memdup(wmem_file_scope(), plain, data_len);
3446 message->data_len = data_len;
3447 message->id = record_id;
3448 message->next = NULL;
3449 memcpy(message->calc_mac, calc_mac, DIGEST_MAX_SIZE);
3450 ssh_debug_printf("%s->sequence_number++ > %d\n", is_response?"server":"client", peer_data->sequence_number);
3452 ssh_message_info_t **pmessage = &packet->messages;
3453 while(*pmessage){
3454 pmessage = &(*pmessage)->next;
3456 *pmessage = message;
3459 offset += message_length + mac_len + 4;
3460 return offset;
3463 proto_item *
3464 ssh_tree_add_mac(proto_tree *tree, tvbuff_t *tvb, const unsigned offset, const unsigned mac_len,
3465 const int hf_mac, const int hf_mac_status, struct expert_field* bad_checksum_expert,
3466 packet_info *pinfo, const uint8_t * calc_mac, const unsigned flags)
3468 // header_field_info *hfinfo = proto_registrar_get_nth(hf_checksum);
3469 proto_item* ti = NULL;
3470 proto_item* ti2;
3471 bool incorrect_mac = true;
3472 char *mac;
3474 // DISSECTOR_ASSERT_HINT(hfinfo != NULL, "Not passed hfi!");
3476 if (flags & PROTO_CHECKSUM_NOT_PRESENT) {
3477 ti = proto_tree_add_uint_format_value(tree, hf_checksum, tvb, offset, len, 0, "[missing]");
3478 proto_item_set_generated(ti);
3479 if (hf_checksum_status > 0) {
3480 ti2 = proto_tree_add_uint(tree, hf_checksum_status, tvb, offset, len, PROTO_CHECKSUM_E_NOT_PRESENT);
3481 proto_item_set_generated(ti2);
3483 return ti;
3486 mac = (char *)tvb_get_ptr(tvb, offset, mac_len);
3487 if (flags & PROTO_CHECKSUM_GENERATED) {
3488 // ti = proto_tree_add_uint(tree, hf_checksum, tvb, offset, len, computed_checksum);
3489 // proto_item_set_generated(ti);
3490 } else {
3491 ti = proto_tree_add_item(tree, hf_mac, tvb, offset, mac_len, ENC_NA);
3492 if (flags & PROTO_CHECKSUM_VERIFY) {
3493 if (flags & (PROTO_CHECKSUM_IN_CKSUM|PROTO_CHECKSUM_ZERO)) {
3494 if (!memcmp(mac, calc_mac, mac_len)) {
3495 proto_item_append_text(ti, " [correct]");
3496 if (hf_mac_status != -1) {
3497 ti2 = proto_tree_add_uint(tree, hf_mac_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
3498 proto_item_set_generated(ti2);
3500 incorrect_mac = false;
3501 } else if (flags & PROTO_CHECKSUM_IN_CKSUM) {
3502 // computed_checksum = in_cksum_shouldbe(checksum, computed_checksum);
3504 } else {
3505 if (!memcmp(mac, calc_mac, mac_len)) {
3506 proto_item_append_text(ti, " [correct]");
3507 if (hf_mac_status != -1) {
3508 ti2 = proto_tree_add_uint(tree, hf_mac_status, tvb, offset, 0, PROTO_CHECKSUM_E_GOOD);
3509 proto_item_set_generated(ti2);
3511 incorrect_mac = false;
3515 if (incorrect_mac) {
3516 if (hf_mac_status != -1) {
3517 ti2 = proto_tree_add_uint(tree, hf_mac_status, tvb, offset, 0, PROTO_CHECKSUM_E_BAD);
3518 proto_item_set_generated(ti2);
3520 if (flags & PROTO_CHECKSUM_ZERO) {
3521 proto_item_append_text(ti, " [incorrect]");
3522 if (bad_checksum_expert != NULL)
3523 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
3524 } else {
3525 char *data = (char *)wmem_alloc(pinfo->pool, mac_len*2 + 1);
3526 *bytes_to_hexstr(data, calc_mac, mac_len) = 0;
3527 proto_item_append_text(ti, " incorrect, computed %s", data);
3528 if (bad_checksum_expert != NULL)
3529 expert_add_info_format(pinfo, ti, bad_checksum_expert, "%s", expert_get_summary(bad_checksum_expert));
3532 } else {
3533 if (hf_mac_status != -1) {
3534 proto_item_append_text(ti, " [unverified]");
3535 ti2 = proto_tree_add_uint(tree, hf_mac_status, tvb, offset, 0, PROTO_CHECKSUM_E_UNVERIFIED);
3536 proto_item_set_generated(ti2);
3541 return ti;
3544 static bool
3545 ssh_decrypt_chacha20(gcry_cipher_hd_t hd,
3546 uint32_t seqnr, uint32_t counter, const unsigned char *ctext, unsigned ctext_len,
3547 unsigned char *plain, unsigned plain_len)
3549 unsigned char seq[8];
3550 unsigned char iv[16];
3552 phton64(seq, (uint64_t)seqnr);
3554 // chacha20 uses a different cipher handle for the packet payload & length
3555 // the payload uses a block counter
3556 if (counter) {
3557 unsigned char ctr[8] = {1,0,0,0,0,0,0,0};
3558 memcpy(iv, ctr, 8);
3559 memcpy(iv+8, seq, 8);
3562 return ((!counter && gcry_cipher_setiv(hd, seq, 8) == 0) ||
3563 (counter && gcry_cipher_setiv(hd, iv, 16) == 0)) &&
3564 gcry_cipher_decrypt(hd, plain, plain_len, ctext, ctext_len) == 0;
3567 static int
3568 ssh_dissect_decrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
3569 struct ssh_peer_data *peer_data, proto_tree *tree,
3570 ssh_message_info_t *message)
3572 int offset = 0; // TODO:
3573 int dissected_len = 0;
3575 char* plaintext = message->plain_data;
3576 unsigned plaintext_len = message->data_len;
3578 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (plaintext_len=%d)", plaintext_len);
3580 tvbuff_t *packet_tvb = tvb_new_child_real_data(tvb, plaintext, plaintext_len, plaintext_len);
3581 add_new_data_source(pinfo, packet_tvb, "Decrypted Packet");
3583 unsigned plen, len;
3584 uint8_t padding_length;
3585 unsigned remain_length;
3586 int last_offset=offset;
3587 unsigned msg_code;
3589 proto_item *ti;
3590 proto_item *msg_type_tree = NULL;
3593 * We use "tvb_ensure_captured_length_remaining()" to make sure there
3594 * actually *is* data remaining.
3596 * This means we're guaranteed that "remain_length" is positive.
3598 remain_length = tvb_ensure_captured_length_remaining(packet_tvb, offset);
3600 * Can we do reassembly?
3602 if (ssh_desegment && pinfo->can_desegment) {
3604 * Yes - would an SSH header starting at this offset
3605 * be split across segment boundaries?
3607 if (remain_length < 4) {
3609 * Yes. Tell the TCP dissector where the data for
3610 * this message starts in the data it handed us and
3611 * that we need "some more data." Don't tell it
3612 * exactly how many bytes we need because if/when we
3613 * ask for even more (after the header) that will
3614 * break reassembly.
3616 pinfo->desegment_offset = offset;
3617 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3618 return offset;
3621 plen = tvb_get_ntohl(packet_tvb, offset) ;
3623 if (ssh_desegment && pinfo->can_desegment) {
3624 if (plen +4 > remain_length) {
3625 pinfo->desegment_offset = offset;
3626 pinfo->desegment_len = plen+4 - remain_length;
3627 return offset;
3631 * Need to check plen > 0x80000000 here
3634 ti = proto_tree_add_uint(tree, hf_ssh_packet_length, packet_tvb,
3635 offset, 4, plen);
3636 if (plen >= 0xffff) {
3637 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
3638 plen = remain_length-4;
3640 offset+=4;
3642 /* padding length */
3643 padding_length = tvb_get_uint8(packet_tvb, offset);
3644 proto_tree_add_uint(tree, hf_ssh_padding_length, packet_tvb, offset, 1, padding_length);
3645 offset += 1;
3647 /* msg_code */
3648 msg_code = tvb_get_uint8(packet_tvb, offset);
3650 /* Transport layer protocol */
3651 /* Generic (1-19) */
3652 if(msg_code >= 1 && msg_code <= 19) {
3653 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
3654 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Transport (generic)");
3655 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3656 dissected_len = ssh_dissect_transport_generic(packet_tvb, pinfo, offset+1, peer_data, msg_type_tree, msg_code) - offset;
3657 // offset = ssh_dissect_transport_generic(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3659 /* Algorithm negotiation (20-29) */
3660 else if(msg_code >=20 && msg_code <= 29) {
3661 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Transport (algorithm negotiation)");
3662 //TODO: See if the complete dissector should be refactored to always got through here first offset = ssh_dissect_transport_algorithm_negotiation(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3664 /* Key exchange method specific (reusable) (30-49) */
3665 else if (msg_code >=30 && msg_code <= 49) {
3666 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Transport (key exchange method specific)");
3667 //TODO: See if the complete dissector should be refactored to always got through here first offset = global_data->kex_specific_dissector(msg_code, packet_tvb, pinfo, offset, msg_type_tree);
3670 /* User authentication protocol */
3671 /* Generic (50-59) */
3672 else if (msg_code >= 50 && msg_code <= 59) {
3673 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
3674 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: User Authentication (generic)");
3675 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3676 dissected_len = ssh_dissect_userauth_generic(packet_tvb, pinfo, offset+1, msg_type_tree, msg_code) - offset;
3677 // TODO: offset = ssh_dissect_userauth_generic(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3679 /* User authentication method specific (reusable) (60-79) */
3680 else if (msg_code >= 60 && msg_code <= 79) {
3681 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
3682 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: User Authentication: (method specific)");
3683 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3684 // TODO: offset = ssh_dissect_userauth_specific(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3685 dissected_len = ssh_dissect_userauth_specific(packet_tvb, pinfo, offset+1, msg_type_tree, msg_code) - offset;
3688 /* Connection protocol */
3689 /* Generic (80-89) */
3690 else if (msg_code >= 80 && msg_code <= 89) {
3691 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
3692 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Connection (generic)");
3693 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3694 // TODO: offset = ssh_dissect_connection_generic(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3695 dissected_len = ssh_dissect_connection_generic(packet_tvb, pinfo, offset+1, msg_type_tree, msg_code) - offset;
3697 /* Channel related messages (90-127) */
3698 else if (msg_code >= 90 && msg_code <= 127) {
3699 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
3700 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Connection: (channel related message)");
3701 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3702 // TODO: offset = ssh_dissect_connection_channel(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3703 dissected_len = ssh_dissect_connection_specific(packet_tvb, pinfo, peer_data, offset+1, msg_type_tree, msg_code, message) - offset;
3706 /* Reserved for client protocols (128-191) */
3707 else if (msg_code >= 128 && msg_code <= 191) {
3708 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
3709 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Client protocol");
3710 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3711 offset+=1;
3712 // TODO: offset = ssh_dissect_client(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
3715 /* Local extensions (192-255) */
3716 else if (msg_code >= 192 && msg_code <= 255) {
3717 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Local extension");
3718 dissected_len = ssh_dissect_local_extension(packet_tvb, pinfo, offset, peer_data, msg_type_tree, msg_code) - offset;
3721 len = plen+4-padding_length-(offset-last_offset);
3722 if (len > 0) {
3723 proto_tree_add_item(msg_type_tree, hf_ssh_payload, packet_tvb, offset, len, ENC_NA);
3725 if(dissected_len!=(int)len){
3726 // expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, len);
3727 expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes [%d]", dissected_len, len, msg_code);
3729 offset +=len;
3731 /* padding */
3732 proto_tree_add_item(tree, hf_ssh_padding_string, packet_tvb, offset, padding_length, ENC_NA);
3733 offset+= padding_length;
3735 if (peer_data->mac_length) {
3736 ssh_tree_add_mac(tree, tvb, offset, peer_data->mac_length, hf_ssh_mac_string, hf_ssh_mac_status, &ei_ssh_mac_bad, pinfo, message->calc_mac,
3737 PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
3738 offset += peer_data->mac_length;
3740 ti = proto_tree_add_uint(tree, hf_ssh_seq_num, tvb, offset, 0, message->sequence_number);
3741 proto_item_set_generated(ti);
3742 return offset;
3745 static int
3746 ssh_dissect_transport_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
3747 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code)
3749 (void)pinfo;
3750 if(msg_code==SSH_MSG_DISCONNECT){
3751 proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_reason, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3752 offset += 4;
3753 unsigned nlen;
3754 nlen = tvb_get_ntohl(packet_tvb, offset) ;
3755 proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_description_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3756 offset += 4;
3757 proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_description, packet_tvb, offset, nlen, ENC_ASCII);
3758 offset += nlen;
3759 nlen = tvb_get_ntohl(packet_tvb, offset) ;
3760 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3761 offset += 4;
3762 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag, packet_tvb, offset, nlen, ENC_ASCII);
3763 offset += nlen;
3764 }else if(msg_code==SSH_MSG_IGNORE){
3765 offset += ssh_tree_add_string(packet_tvb, offset, msg_type_tree, hf_ssh_ignore_data, hf_ssh_ignore_data_length);
3766 }else if(msg_code==SSH_MSG_DEBUG){
3767 unsigned slen;
3768 proto_tree_add_item(msg_type_tree, hf_ssh_debug_always_display, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3769 offset += 1;
3770 slen = tvb_get_ntohl(packet_tvb, offset) ;
3771 proto_tree_add_item(msg_type_tree, hf_ssh_debug_message_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3772 offset += 4;
3773 proto_tree_add_item(msg_type_tree, hf_ssh_debug_message, packet_tvb, offset, slen, ENC_UTF_8);
3774 offset += slen;
3775 slen = tvb_get_ntohl(packet_tvb, offset) ;
3776 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3777 offset += 4;
3778 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag, packet_tvb, offset, slen, ENC_ASCII);
3779 offset += slen;
3780 }else if(msg_code==SSH_MSG_SERVICE_REQUEST){
3781 unsigned nlen;
3782 nlen = tvb_get_ntohl(packet_tvb, offset) ;
3783 proto_tree_add_item(msg_type_tree, hf_ssh_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3784 offset += 4;
3785 proto_tree_add_item(msg_type_tree, hf_ssh_service_name, packet_tvb, offset, nlen, ENC_ASCII);
3786 offset += nlen;
3787 }else if(msg_code==SSH_MSG_SERVICE_ACCEPT){
3788 unsigned nlen;
3789 nlen = tvb_get_ntohl(packet_tvb, offset) ;
3790 proto_tree_add_item(msg_type_tree, hf_ssh_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3791 offset += 4;
3792 proto_tree_add_item(msg_type_tree, hf_ssh_service_name, packet_tvb, offset, nlen, ENC_ASCII);
3793 offset += nlen;
3794 }else if(msg_code==SSH_MSG_EXT_INFO){
3795 unsigned ext_cnt;
3796 ext_cnt = tvb_get_ntohl(packet_tvb, offset);
3797 proto_tree_add_item(msg_type_tree, hf_ssh_ext_count, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3798 offset += 4;
3799 for(unsigned ext_index = 0; ext_index < ext_cnt; ext_index++) {
3800 offset = ssh_dissect_rfc8308_extension(packet_tvb, pinfo, offset, peer_data, msg_type_tree);
3803 return offset;
3806 static int
3807 ssh_dissect_rfc8308_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
3808 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree)
3810 (void)pinfo;
3811 unsigned ext_name_slen = tvb_get_ntohl(packet_tvb, offset);
3812 uint8_t *ext_name = tvb_get_string_enc(pinfo->pool, packet_tvb, offset + 4, ext_name_slen, ENC_ASCII);
3813 unsigned ext_value_slen = tvb_get_ntohl(packet_tvb, offset + 4 + ext_name_slen);
3814 unsigned ext_len = 8 + ext_name_slen + ext_value_slen;
3815 proto_item *ext_tree = proto_tree_add_subtree_format(msg_type_tree, packet_tvb, offset, ext_len, ett_extension, NULL, "Extension: %s", ext_name);
3817 proto_tree_add_item(ext_tree, hf_ssh_ext_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3818 offset += 4;
3819 proto_tree_add_item(ext_tree, hf_ssh_ext_name, packet_tvb, offset, ext_name_slen, ENC_ASCII);
3820 offset += ext_name_slen;
3821 proto_tree_add_item(ext_tree, hf_ssh_ext_value_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3822 offset += 4;
3823 proto_tree_add_item(ext_tree, hf_ssh_ext_value, packet_tvb, offset, ext_value_slen, ENC_NA);
3825 if (g_str_equal(ext_name, "server-sig-algs")) {
3826 // server-sig-algs (RFC8308 Sec. 3.1)
3827 proto_tree_add_item(ext_tree, hf_ssh_ext_server_sig_algs_algorithms, packet_tvb, offset, ext_value_slen, ENC_ASCII);
3828 offset += ext_value_slen;
3829 } else if (g_str_equal(ext_name, "delay-compression")) {
3830 // delay-compression (RFC8308 Sec 3.2)
3831 unsigned slen;
3832 slen = tvb_get_ntohl(packet_tvb, offset);
3833 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_client_to_server_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3834 offset += 4;
3835 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_client_to_server, packet_tvb, offset, slen, ENC_ASCII);
3836 offset += slen;
3837 slen = tvb_get_ntohl(packet_tvb, offset);
3838 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_server_to_client_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3839 offset += 4;
3840 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_server_to_client, packet_tvb, offset, slen, ENC_ASCII);
3841 offset += slen;
3842 } else if (g_str_equal(ext_name, "no-flow-control")) {
3843 // no-flow-control (RFC 8308 Sec 3.3)
3844 proto_tree_add_item(ext_tree, hf_ssh_ext_no_flow_control_value, packet_tvb, offset, ext_value_slen, ENC_ASCII);
3845 offset += ext_value_slen;
3846 } else if (g_str_equal(ext_name, "elevation")) {
3847 // elevation (RFC 8308 Sec 3.4)
3848 proto_tree_add_item(ext_tree, hf_ssh_ext_elevation_value, packet_tvb, offset, ext_value_slen, ENC_ASCII);
3849 offset += ext_value_slen;
3850 } else if (g_str_equal(ext_name, "publickey-algorithms@roumenpetrov.info")) {
3851 // publickey-algorithms@roumenpetrov.info (proprietary)
3852 proto_tree_add_item(ext_tree, hf_ssh_ext_prop_publickey_algorithms_algorithms, packet_tvb, offset, ext_value_slen, ENC_ASCII);
3853 offset += ext_value_slen;
3854 } else if (g_str_equal(ext_name, "ping@openssh.com")) {
3855 // ping@openssh.com (proprietary w/ primitive extension value)
3856 peer_data->global_data->ext_ping_openssh_offered = true;
3857 offset += ext_value_slen;
3858 } else {
3859 offset += ext_value_slen;
3862 // The following extensions do not require advanced dissection:
3863 // - global-requests-ok
3864 // - ext-auth-info
3865 // - publickey-hostbound@openssh.com
3866 // - ext-info-in-auth@openssh.com
3868 return offset;
3871 static int
3872 ssh_dissect_userauth_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
3873 int offset, proto_item *msg_type_tree, unsigned msg_code)
3875 if(msg_code==SSH_MSG_USERAUTH_REQUEST){
3876 unsigned slen;
3877 slen = tvb_get_ntohl(packet_tvb, offset) ;
3878 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_user_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3879 offset += 4;
3880 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_user_name, packet_tvb, offset, slen, ENC_ASCII);
3881 offset += slen;
3882 slen = tvb_get_ntohl(packet_tvb, offset) ;
3883 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3884 offset += 4;
3885 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_service_name, packet_tvb, offset, slen, ENC_ASCII);
3886 offset += slen;
3887 slen = tvb_get_ntohl(packet_tvb, offset) ;
3888 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_method_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3889 offset += 4;
3890 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_method_name, packet_tvb, offset, slen, ENC_ASCII);
3892 uint8_t* key_type;
3893 key_type = tvb_get_string_enc(pinfo->pool, packet_tvb, offset, slen, ENC_ASCII|ENC_NA);
3894 offset += slen;
3895 if (0 == strcmp(key_type, "none")) {
3896 }else if (0 == strcmp(key_type, "publickey")) {
3897 uint8_t bHaveSignature = tvb_get_uint8(packet_tvb, offset);
3898 int dissected_len = 0;
3899 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_have_signature, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3900 offset += 1;
3901 slen = tvb_get_ntohl(packet_tvb, offset) ;
3902 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3903 offset += 4;
3904 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name, packet_tvb, offset, slen, ENC_ASCII);
3905 offset += slen;
3906 proto_item *blob_tree = NULL;
3907 slen = tvb_get_ntohl(packet_tvb, offset) ;
3908 proto_tree_add_item(msg_type_tree, hf_ssh_blob_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3909 offset += 4;
3910 blob_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, slen, ett_userauth_pk_blob, NULL, "Public key blob");
3911 // proto_tree_add_item(blob_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3912 dissected_len = ssh_dissect_public_key_blob(packet_tvb, pinfo, offset, blob_tree) - offset;
3913 if(dissected_len!=(int)slen){
3914 expert_add_info_format(pinfo, blob_tree, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
3916 offset += slen;
3917 if(bHaveSignature){
3918 slen = tvb_get_ntohl(packet_tvb, offset) ;
3919 proto_tree_add_item(msg_type_tree, hf_ssh_signature_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3920 offset += 4;
3921 proto_item *signature_tree = NULL;
3922 signature_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, slen, ett_userauth_pk_signautre, NULL, "Public key signature");
3923 dissected_len = ssh_dissect_public_key_signature(packet_tvb, pinfo, offset, signature_tree) - offset;
3924 if(dissected_len!=(int)slen){
3925 expert_add_info_format(pinfo, signature_tree, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
3927 offset += slen;
3929 }else if (0 == strcmp(key_type, "password")) {
3930 uint8_t bChangePassword = tvb_get_uint8(packet_tvb, offset);
3931 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_change_password, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3932 offset += 1;
3933 slen = tvb_get_ntohl(packet_tvb, offset) ;
3934 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_password_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3935 offset += 4;
3936 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_password, packet_tvb, offset, slen, ENC_ASCII);
3937 offset += slen;
3938 if(bChangePassword){
3939 slen = tvb_get_ntohl(packet_tvb, offset) ;
3940 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_new_password_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3941 offset += 4;
3942 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_new_password, packet_tvb, offset, slen, ENC_ASCII);
3943 offset += slen;
3945 }else{
3948 }else if(msg_code==SSH_MSG_USERAUTH_FAILURE){
3949 unsigned slen;
3950 slen = tvb_get_ntohl(packet_tvb, offset) ;
3951 proto_tree_add_item(msg_type_tree, hf_ssh_auth_failure_list_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3952 offset += 4;
3953 proto_tree_add_item(msg_type_tree, hf_ssh_auth_failure_list, packet_tvb, offset, slen, ENC_ASCII);
3954 offset += slen;
3955 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_partial_success, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
3956 offset += 1;
3958 return offset;
3961 static int
3962 ssh_dissect_userauth_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
3963 int offset, proto_item *msg_type_tree, unsigned msg_code)
3965 if(msg_code==SSH_MSG_USERAUTH_PK_OK){
3966 proto_item *ti;
3967 int dissected_len = 0;
3968 unsigned slen;
3969 slen = tvb_get_ntohl(packet_tvb, offset) ;
3970 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3971 offset += 4;
3972 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name, packet_tvb, offset, slen, ENC_ASCII);
3973 offset += slen;
3974 proto_item *blob_tree = NULL;
3975 slen = tvb_get_ntohl(packet_tvb, offset) ;
3976 ti = proto_tree_add_item(msg_type_tree, hf_ssh_blob_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
3977 offset += 4;
3978 blob_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, slen, ett_userauth_pk_blob, NULL, "Public key blob");
3979 dissected_len = ssh_dissect_public_key_blob(packet_tvb, pinfo, offset, blob_tree) - offset;
3980 if(dissected_len!=(int)slen){
3981 expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
3983 offset += slen;
3985 return offset;
3988 static void
3989 ssh_process_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, ssh_channel_info_t *channel)
3991 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
3992 if (channel->handle) {
3993 call_dissector(channel->handle, next_tvb, pinfo, proto_tree_get_root(tree));
3994 } else {
3995 call_data_dissector(next_tvb, pinfo, proto_tree_get_root(tree));
3999 static void
4000 print_ssh_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *ssh_tree, packet_info *pinfo, tvbuff_t *next_tvb)
4002 proto_item *ssh_tree_item, *frag_tree_item;
4005 * The subdissector thought it was completely
4006 * desegmented (although the stuff at the
4007 * end may, in turn, require desegmentation),
4008 * so we show a tree with all segments.
4010 show_fragment_tree(ipfd_head, &ssh_segment_items,
4011 tree, pinfo, next_tvb, &frag_tree_item);
4013 * The toplevel fragment subtree is now
4014 * behind all desegmented data; move it
4015 * right behind the SSH tree.
4017 ssh_tree_item = proto_tree_get_parent(ssh_tree);
4018 /* The SSH protocol item is up a few levels from the message tree */
4019 ssh_tree_item = proto_item_get_parent_nth(ssh_tree_item, 2);
4020 if (frag_tree_item && ssh_tree_item) {
4021 proto_tree_move_item(tree, ssh_tree_item, frag_tree_item);
4025 static uint32_t
4026 ssh_msp_fragment_id(struct tcp_multisegment_pdu *msp)
4029 * If a frame contains multiple PDUs, then "first_frame" is not
4030 * sufficient to uniquely identify groups of fragments. Therefore we use
4031 * the tcp reassembly functions that also test msp->seq (the position of
4032 * the initial fragment in the SSH channel).
4034 return msp->first_frame;
4037 static void
4038 ssh_proto_tree_add_segment_data(
4039 proto_tree *tree,
4040 tvbuff_t *tvb,
4041 int offset,
4042 int length,
4043 const char *prefix)
4045 proto_tree_add_bytes_format(
4046 tree,
4047 hf_ssh_segment_data,
4048 tvb,
4049 offset,
4050 length,
4051 NULL,
4052 "%sSSH segment data (%u %s)",
4053 prefix != NULL ? prefix : "",
4054 length == -1 ? tvb_reported_length_remaining(tvb, offset) : length,
4055 plurality(length, "byte", "bytes"));
4058 static void
4059 desegment_ssh(tvbuff_t *tvb, packet_info *pinfo, uint32_t seq,
4060 uint32_t nxtseq, proto_tree *tree, ssh_channel_info_t *channel)
4062 fragment_head *ipfd_head;
4063 bool must_desegment;
4064 bool called_dissector;
4065 int another_pdu_follows;
4066 bool another_segment_in_frame = false;
4067 int deseg_offset, offset = 0;
4068 uint32_t deseg_seq;
4069 int nbytes;
4070 proto_item *item;
4071 struct tcp_multisegment_pdu *msp;
4072 bool first_pdu = true;
4074 again:
4075 ipfd_head = NULL;
4076 must_desegment = false;
4077 called_dissector = false;
4078 another_pdu_follows = 0;
4079 msp = NULL;
4082 * Initialize these to assume no desegmentation.
4083 * If that's not the case, these will be set appropriately
4084 * by the subdissector.
4086 pinfo->desegment_offset = 0;
4087 pinfo->desegment_len = 0;
4090 * Initialize this to assume that this segment will just be
4091 * added to the middle of a desegmented chunk of data, so
4092 * that we should show it all as data.
4093 * If that's not the case, it will be set appropriately.
4095 deseg_offset = offset;
4097 /* If we've seen this segment before (e.g., it's a retransmission),
4098 * there's nothing for us to do. Certainly, don't add it to the list
4099 * of multisegment_pdus (that would cause subsequent lookups to find
4100 * the retransmission instead of the original transmission, breaking
4101 * dissection of the desegmented pdu if we'd already seen the end of
4102 * the pdu).
4104 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(channel->multisegment_pdus, seq))) {
4105 const char *prefix;
4106 bool is_retransmission = false;
4108 if (msp->first_frame == pinfo->num) {
4109 /* This must be after the first pass. */
4110 prefix = "";
4111 if (msp->last_frame == pinfo->num) {
4112 col_clear(pinfo->cinfo, COL_INFO);
4113 } else {
4114 if (first_pdu) {
4115 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[SSH segment of a reassembled PDU]");
4118 } else {
4119 prefix = "Retransmitted ";
4120 is_retransmission = true;
4123 if (!is_retransmission) {
4124 ipfd_head = fragment_get(&ssh_reassembly_table, pinfo, msp->first_frame, msp);
4125 if (ipfd_head != NULL && ipfd_head->reassembled_in !=0 &&
4126 ipfd_head->reassembled_in != pinfo->num) {
4127 /* Show what frame this was reassembled in if not this one. */
4128 item=proto_tree_add_uint(tree, *ssh_segment_items.hf_reassembled_in,
4129 tvb, 0, 0, ipfd_head->reassembled_in);
4130 proto_item_set_generated(item);
4133 nbytes = tvb_reported_length_remaining(tvb, offset);
4134 ssh_proto_tree_add_segment_data(tree, tvb, offset, nbytes, prefix);
4135 return;
4138 /* Else, find the most previous PDU starting before this sequence number */
4139 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(channel->multisegment_pdus, seq-1);
4140 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
4141 int len;
4143 if (!PINFO_FD_VISITED(pinfo)) {
4144 msp->last_frame = pinfo->num;
4145 msp->last_frame_time = pinfo->abs_ts;
4148 /* OK, this PDU was found, which means the segment continues
4149 * a higher-level PDU and that we must desegment it.
4151 if (msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4152 /* The dissector asked for the entire segment */
4153 len = MAX(0, tvb_reported_length_remaining(tvb, offset));
4154 } else {
4155 len = MIN(nxtseq, msp->nxtpdu) - seq;
4158 ipfd_head = fragment_add(&ssh_reassembly_table, tvb, offset,
4159 pinfo, ssh_msp_fragment_id(msp), msp,
4160 seq - msp->seq,
4161 len, (LT_SEQ (nxtseq,msp->nxtpdu)));
4163 if (!PINFO_FD_VISITED(pinfo)
4164 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4165 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
4167 /* If we consumed the entire segment there is no
4168 * other pdu starting anywhere inside this segment.
4169 * So update nxtpdu to point at least to the start
4170 * of the next segment.
4171 * (If the subdissector asks for even more data we
4172 * will advance nxtpdu even further later down in
4173 * the code.)
4175 msp->nxtpdu = nxtseq;
4178 if ( (msp->nxtpdu < nxtseq)
4179 && (msp->nxtpdu >= seq)
4180 && (len > 0)) {
4181 another_pdu_follows = msp->nxtpdu - seq;
4183 } else {
4184 /* This segment was not found in our table, so it doesn't
4185 * contain a continuation of a higher-level PDU.
4186 * Call the normal subdissector.
4188 ssh_process_payload(tvb, offset, pinfo, tree, channel);
4189 called_dissector = true;
4191 /* Did the subdissector ask us to desegment some more data
4192 * before it could handle the packet?
4193 * If so we have to create some structures in our table but
4194 * this is something we only do the first time we see this
4195 * packet.
4197 if (pinfo->desegment_len) {
4198 if (!PINFO_FD_VISITED(pinfo))
4199 must_desegment = true;
4202 * Set "deseg_offset" to the offset in "tvb"
4203 * of the first byte of data that the
4204 * subdissector didn't process.
4206 deseg_offset = offset + pinfo->desegment_offset;
4209 /* Either no desegmentation is necessary, or this is
4210 * segment contains the beginning but not the end of
4211 * a higher-level PDU and thus isn't completely
4212 * desegmented.
4214 ipfd_head = NULL;
4217 /* is it completely desegmented? */
4218 if (ipfd_head && ipfd_head->reassembled_in == pinfo->num) {
4220 * Yes, we think it is.
4221 * We only call subdissector for the last segment.
4222 * Note that the last segment may include more than what
4223 * we needed.
4225 if (nxtseq < msp->nxtpdu) {
4227 * This is *not* the last segment. It is part of a PDU in the same
4228 * frame, so no another PDU can follow this one.
4229 * Do not reassemble SSH yet, it will be done in the final segment.
4230 * (If we are reassembling at FIN, we will do that in dissect_ssl()
4231 * after iterating through all the records.)
4232 * Clear the Info column and avoid displaying [SSH segment of a
4233 * reassembled PDU], the payload dissector will typically set it.
4234 * (This is needed here for the second pass.)
4236 another_pdu_follows = 0;
4237 col_clear(pinfo->cinfo, COL_INFO);
4238 another_segment_in_frame = true;
4239 } else {
4241 * OK, this is the last segment of the PDU and also the
4242 * last segment in this frame.
4243 * Let's call the subdissector with the desegmented
4244 * data.
4246 tvbuff_t *next_tvb;
4247 int old_len;
4250 * Reset column in case multiple SSH segments form the PDU
4251 * and this last SSH segment is not in the first TCP segment of
4252 * this frame.
4253 * XXX prevent clearing the column if the last layer is not SSH?
4255 /* Clear column during the first pass. */
4256 col_clear(pinfo->cinfo, COL_INFO);
4258 /* create a new TVB structure for desegmented data */
4259 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
4261 /* add desegmented data to the data source list */
4262 add_new_data_source(pinfo, next_tvb, "Reassembled SSH");
4264 /* call subdissector */
4265 ssh_process_payload(next_tvb, 0, pinfo, tree, channel);
4266 called_dissector = true;
4269 * OK, did the subdissector think it was completely
4270 * desegmented, or does it think we need even more
4271 * data?
4273 old_len = (int)(tvb_reported_length(next_tvb) - tvb_reported_length_remaining(tvb, offset));
4274 if (pinfo->desegment_len && pinfo->desegment_offset <= old_len) {
4276 * "desegment_len" isn't 0, so it needs more
4277 * data for something - and "desegment_offset"
4278 * is before "old_len", so it needs more data
4279 * to dissect the stuff we thought was
4280 * completely desegmented (as opposed to the
4281 * stuff at the beginning being completely
4282 * desegmented, but the stuff at the end
4283 * being a new higher-level PDU that also
4284 * needs desegmentation).
4286 fragment_set_partial_reassembly(&ssh_reassembly_table,
4287 pinfo, ssh_msp_fragment_id(msp), msp);
4288 /* Update msp->nxtpdu to point to the new next
4289 * pdu boundary.
4291 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
4292 /* We want reassembly of at least one
4293 * more segment so set the nxtpdu
4294 * boundary to one byte into the next
4295 * segment.
4296 * This means that the next segment
4297 * will complete reassembly even if it
4298 * is only one single byte in length.
4300 msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + 1;
4301 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
4302 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
4303 /* This is not the first segment, and we thought reassembly
4304 * would be done now, but now we know we desegment at FIN.
4305 * E.g., a HTTP response where the headers were split
4306 * across segments (so previous ONE_MORE_SEGMENT) and
4307 * also no Content-Length (so now DESEGMENT_UNTIL_FIN).
4309 channel->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
4310 msp->nxtpdu = nxtseq + 0x40000000;
4311 } else {
4312 msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + pinfo->desegment_len;
4314 /* Since we need at least some more data
4315 * there can be no pdu following in the
4316 * tail of this segment.
4318 another_pdu_follows = 0;
4319 } else {
4321 * Show the stuff in this TCP segment as
4322 * just raw TCP segment data.
4324 nbytes = another_pdu_follows > 0
4325 ? another_pdu_follows
4326 : tvb_reported_length_remaining(tvb, offset);
4327 ssh_proto_tree_add_segment_data(tree, tvb, offset, nbytes, NULL);
4329 /* Show details of the reassembly */
4330 print_ssh_fragment_tree(ipfd_head, proto_tree_get_root(tree), tree, pinfo, next_tvb);
4332 /* Did the subdissector ask us to desegment
4333 * some more data? This means that the data
4334 * at the beginning of this segment completed
4335 * a higher-level PDU, but the data at the
4336 * end of this segment started a higher-level
4337 * PDU but didn't complete it.
4339 * If so, we have to create some structures
4340 * in our table, but this is something we
4341 * only do the first time we see this packet.
4343 if (pinfo->desegment_len) {
4344 if (!PINFO_FD_VISITED(pinfo))
4345 must_desegment = true;
4347 /* The stuff we couldn't dissect
4348 * must have come from this segment,
4349 * so it's all in "tvb".
4351 * "pinfo->desegment_offset" is
4352 * relative to the beginning of
4353 * "next_tvb"; we want an offset
4354 * relative to the beginning of "tvb".
4356 * First, compute the offset relative
4357 * to the *end* of "next_tvb" - i.e.,
4358 * the number of bytes before the end
4359 * of "next_tvb" at which the
4360 * subdissector stopped. That's the
4361 * length of "next_tvb" minus the
4362 * offset, relative to the beginning
4363 * of "next_tvb, at which the
4364 * subdissector stopped.
4366 deseg_offset = ipfd_head->datalen - pinfo->desegment_offset;
4368 /* "tvb" and "next_tvb" end at the
4369 * same byte of data, so the offset
4370 * relative to the end of "next_tvb"
4371 * of the byte at which we stopped
4372 * is also the offset relative to
4373 * the end of "tvb" of the byte at
4374 * which we stopped.
4376 * Convert that back into an offset
4377 * relative to the beginning of
4378 * "tvb", by taking the length of
4379 * "tvb" and subtracting the offset
4380 * relative to the end.
4382 deseg_offset = tvb_reported_length(tvb) - deseg_offset;
4388 if (must_desegment) {
4389 /* If the dissector requested "reassemble until FIN"
4390 * just set this flag for the flow and let reassembly
4391 * proceed at normal. We will check/pick up these
4392 * reassembled PDUs later down in dissect_tcp() when checking
4393 * for the FIN flag.
4395 if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
4396 channel->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
4399 * The sequence number at which the stuff to be desegmented
4400 * starts is the sequence number of the byte at an offset
4401 * of "deseg_offset" into "tvb".
4403 * The sequence number of the byte at an offset of "offset"
4404 * is "seq", i.e. the starting sequence number of this
4405 * segment, so the sequence number of the byte at
4406 * "deseg_offset" is "seq + (deseg_offset - offset)".
4408 deseg_seq = seq + (deseg_offset - offset);
4410 if (((nxtseq - deseg_seq) <= 1024*1024)
4411 && (!PINFO_FD_VISITED(pinfo))) {
4412 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
4413 /* The subdissector asked to reassemble using the
4414 * entire next segment.
4415 * Just ask reassembly for one more byte
4416 * but set this msp flag so we can pick it up
4417 * above.
4419 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
4420 deseg_seq, nxtseq+1, channel->multisegment_pdus);
4421 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
4422 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
4423 /* Set nxtseq very large so that reassembly won't happen
4424 * until we force it at the end of the stream in dissect_ssl()
4425 * outside this function.
4427 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
4428 deseg_seq, nxtseq+0x40000000, channel->multisegment_pdus);
4429 } else {
4430 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
4431 deseg_seq, nxtseq+pinfo->desegment_len, channel->multisegment_pdus);
4434 /* add this segment as the first one for this new pdu */
4435 fragment_add(&ssh_reassembly_table, tvb, deseg_offset,
4436 pinfo, ssh_msp_fragment_id(msp), msp,
4437 0, nxtseq - deseg_seq,
4438 LT_SEQ(nxtseq, msp->nxtpdu));
4442 if (!called_dissector || pinfo->desegment_len != 0) {
4443 if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
4444 ipfd_head->reassembled_in != pinfo->num &&
4445 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
4447 * We know what other frame this PDU is reassembled in;
4448 * let the user know.
4450 item=proto_tree_add_uint(tree, *ssh_segment_items.hf_reassembled_in,
4451 tvb, 0, 0, ipfd_head->reassembled_in);
4452 proto_item_set_generated(item);
4456 * Either we didn't call the subdissector at all (i.e.,
4457 * this is a segment that contains the middle of a
4458 * higher-level PDU, but contains neither the beginning
4459 * nor the end), or the subdissector couldn't dissect it
4460 * all, as some data was missing (i.e., it set
4461 * "pinfo->desegment_len" to the amount of additional
4462 * data it needs).
4464 if (!another_segment_in_frame && pinfo->desegment_offset == 0) {
4466 * It couldn't, in fact, dissect any of it (the
4467 * first byte it couldn't dissect is at an offset
4468 * of "pinfo->desegment_offset" from the beginning
4469 * of the payload, and that's 0).
4470 * Just mark this as SSH.
4473 /* SFTP checks the length before setting the protocol column.
4474 * If other subdissectors don't do this, we'd want to set the
4475 * protocol column back - but we want to get the SSH version
4477 //col_set_str(pinfo->cinfo, COL_PROTOCOL,
4478 // val_to_str_const(session->version, ssl_version_short_names, "SSH"));
4479 if (first_pdu) {
4480 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[SSH segment of a reassembled PDU]");
4485 * Show what's left in the packet as just raw SSH segment data.
4486 * XXX - remember what protocol the last subdissector
4487 * was, and report it as a continuation of that, instead?
4489 nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
4490 ssh_proto_tree_add_segment_data(tree, tvb, deseg_offset, nbytes, NULL);
4492 pinfo->can_desegment = 0;
4493 pinfo->desegment_offset = 0;
4494 pinfo->desegment_len = 0;
4496 if (another_pdu_follows) {
4497 /* there was another pdu following this one. */
4498 pinfo->can_desegment=2;
4499 /* we also have to prevent the dissector from changing the
4500 * PROTOCOL and INFO colums since what follows may be an
4501 * incomplete PDU and we don't want it be changed back from
4502 * <Protocol> to <SSH>
4504 col_set_fence(pinfo->cinfo, COL_INFO);
4505 col_set_writable(pinfo->cinfo, COL_PROTOCOL, false);
4506 first_pdu = false;
4507 offset += another_pdu_follows;
4508 seq += another_pdu_follows;
4509 goto again;
4513 static void
4514 ssh_dissect_channel_data(tvbuff_t *tvb, packet_info *pinfo,
4515 struct ssh_peer_data *peer_data _U_, proto_tree *tree,
4516 ssh_message_info_t *message _U_, ssh_channel_info_t *channel)
4519 uint16_t save_can_desegment = pinfo->can_desegment;
4521 if (ssh_desegment) {
4522 pinfo->can_desegment = 2;
4523 desegment_ssh(tvb, pinfo, message->byte_seq, message->next_byte_seq, tree, channel);
4524 } else {
4525 pinfo->can_desegment = 0;
4526 bool save_fragmented = pinfo->fragmented;
4527 pinfo->fragmented = true;
4529 ssh_process_payload(tvb, 0, pinfo, tree, channel);
4530 pinfo->fragmented = save_fragmented;
4533 pinfo->can_desegment = save_can_desegment;
4536 static int
4537 ssh_dissect_connection_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
4538 struct ssh_peer_data *peer_data, int offset, proto_tree *msg_type_tree,
4539 unsigned msg_code, ssh_message_info_t *message)
4541 uint32_t recipient_channel, sender_channel;
4543 if(msg_code==SSH_MSG_CHANNEL_OPEN){
4544 uint32_t slen;
4545 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_type_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4546 offset += 4;
4547 proto_tree_add_item(msg_type_tree, hf_ssh_connection_type_name, packet_tvb, offset, slen, ENC_UTF_8);
4548 offset += slen;
4549 proto_tree_add_item(msg_type_tree, hf_ssh_connection_sender_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4550 offset += 4;
4551 proto_tree_add_item(msg_type_tree, hf_ssh_connection_initial_window, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4552 offset += 4;
4553 proto_tree_add_item(msg_type_tree, hf_ssh_connection_maximum_packet_size, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4554 offset += 4;
4555 }else if(msg_code==SSH_MSG_CHANNEL_OPEN_CONFIRMATION){
4556 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
4557 offset += 4;
4558 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_sender_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &sender_channel);
4559 offset += 4;
4560 if (!PINFO_FD_VISITED(pinfo)) {
4561 create_channel(peer_data, recipient_channel, sender_channel);
4563 proto_tree_add_item(msg_type_tree, hf_ssh_connection_initial_window, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4564 offset += 4;
4565 proto_tree_add_item(msg_type_tree, hf_ssh_connection_maximum_packet_size, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4566 offset += 4;
4567 }else if(msg_code==SSH_MSG_CHANNEL_WINDOW_ADJUST){
4568 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4569 offset += 4;
4570 proto_tree_add_item(msg_type_tree, hf_ssh_channel_window_adjust, packet_tvb, offset, 4, ENC_BIG_ENDIAN); // TODO: maintain count of transferred bytes and window size
4571 offset += 4;
4572 }else if(msg_code==SSH_MSG_CHANNEL_DATA){
4573 proto_item *ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
4574 offset += 4;
4575 // TODO: process according to the type of channel
4576 uint32_t slen;
4577 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_data_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4578 offset += 4;
4579 tvbuff_t *next_tvb = tvb_new_subset_length(packet_tvb, offset, slen);
4581 ssh_channel_info_t *channel = get_channel_info_for_channel(peer_data, recipient_channel);
4582 if (channel) {
4583 if (!PINFO_FD_VISITED(pinfo)) {
4584 message->byte_seq = channel->byte_seq;
4585 channel->byte_seq += slen;
4586 message->next_byte_seq = channel->byte_seq;
4588 ssh_dissect_channel_data(next_tvb, pinfo, peer_data, msg_type_tree, message, channel);
4589 } else {
4590 expert_add_info_format(pinfo, ti, &ei_ssh_channel_number, "Could not find configuration for channel %d", recipient_channel);
4592 offset += slen;
4593 }else if(msg_code==SSH_MSG_CHANNEL_EOF){
4594 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4595 offset += 4;
4596 }else if(msg_code==SSH_MSG_CHANNEL_CLOSE){
4597 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4598 offset += 4;
4599 }else if(msg_code==SSH_MSG_CHANNEL_REQUEST){
4600 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
4601 offset += 4;
4602 const uint8_t* request_name;
4603 uint32_t slen;
4604 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_request_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4605 offset += 4;
4606 proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_channel_request_name, packet_tvb, offset, slen, ENC_UTF_8, pinfo->pool, &request_name);
4607 offset += slen;
4608 proto_tree_add_item(msg_type_tree, hf_ssh_channel_request_want_reply, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4609 offset += 1;
4610 /* RFC 4254 6.5: "Only one of these requests ["shell", "exec",
4611 * or "subsystem"] can succeed per channel." Set up the
4612 * appropriate handler for future CHANNEL_DATA and
4613 * CHANNEL_EXTENDED_DATA messages on the channel.
4615 if (0 == strcmp(request_name, "subsystem")) {
4616 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_subsystem_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4617 offset += 4;
4618 const uint8_t* subsystem_name;
4619 proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_subsystem_name, packet_tvb, offset, slen, ENC_UTF_8, pinfo->pool, &subsystem_name);
4620 set_subdissector_for_channel(peer_data, recipient_channel, subsystem_name);
4621 offset += slen;
4622 }else if (0 == strcmp(request_name, "exit-status")) {
4623 proto_tree_add_item(msg_type_tree, hf_ssh_exit_status, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4624 offset += 4;
4626 }else if(msg_code==SSH_MSG_CHANNEL_SUCCESS){
4627 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4628 offset += 4;
4630 return offset;
4633 /* Channel mapping {{{ */
4635 /* The usual flow:
4636 * 1. client sends SSH_MSG_CHANNEL_OPEN with its (sender) channel number
4637 * 2. server responds with SSH_MSG_CHANNEL_OPEN_CONFIRMATION with
4638 * its channel number and echoing the client's number, creating
4639 * a bijective map
4640 * 3. client sends SSH_MSG_CHANNEL_REQUEST which has the name of
4641 * the shell, command, or subsystem to start. This has the recipient's
4642 * channel number (i.e. the server's)
4643 * 4. server may send back a SSG_MSG_CHANNEL_SUCCESS (or _FAILURE) with
4644 * the the recipient (i.e., client) channel number, but this does not
4645 * contain the subsystem name or anything identifying the request to
4646 * which it responds. It MUST be sent in the same order as the
4647 * corresponding request message (RFC 4254 4 Global Requests), so we
4648 * could track it that way, but for our purposes we just treat all
4649 * requests as successes. (If not, either there won't be data or another
4650 * request will supercede it later.)
4652 * Either side can open a channel (RFC 4254 5 Channel Mechanism). The
4653 * typical flow is the client opening a channel, but in the case of
4654 * remote port forwarding (7 TCP/IP Port Forwarding) the directions are
4655 * swapped. For port forwarding, all the information is contained in the
4656 * SSH_MSG_CHANNEL_OPEN, there is no SSH_MSG_CHANNEL_REQUEST.
4658 * XXX: Channel numbers can be re-used after being closed (5.3 Closing a
4659 * Channel), but not necessarily mapped to the same channel number on the
4660 * other side. If that actually happens, the right way to handle this is
4661 * to track the state changes over time for random packet access (e.g.,
4662 * using a multimap with the packet number instead of maps.)
4665 static struct ssh_peer_data*
4666 get_other_peer_data(struct ssh_peer_data *peer_data)
4668 bool is_server = &peer_data->global_data->peer_data[SERVER_PEER_DATA]==peer_data;
4669 if (is_server) {
4670 return &peer_data->global_data->peer_data[CLIENT_PEER_DATA];
4671 } else {
4672 return &peer_data->global_data->peer_data[SERVER_PEER_DATA];
4676 /* Create pairings between a recipient channel and the sender's channel,
4677 * from a SSH_MSG_CHANNEL_OPEN_CONFIRMATION. */
4678 static void
4679 create_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, uint32_t sender_channel)
4681 if (peer_data->channel_info == NULL) {
4682 peer_data->channel_info = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
4684 wmem_map_insert(peer_data->channel_info, GUINT_TO_POINTER(sender_channel), GUINT_TO_POINTER(recipient_channel));
4686 if (peer_data->channel_handles == NULL) {
4687 peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
4690 ssh_channel_info_t *new_channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t);
4691 new_channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
4692 wmem_map_insert(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel), new_channel);
4694 /* If the recipient channel is already configured in the other direction,
4695 * set the handle. We need this if we eventually handle port forwarding,
4696 * where all the information to handle the traffic is sent in the
4697 * SSH_MSG_CHANNEL_OPEN message before the CONFIRMATION. It might also
4698 * help if the packets are out of order (i.e. we get the client
4699 * CHANNEL_REQUEST before the CHANNEL_OPEN_CONFIRMATION.)
4701 struct ssh_peer_data *other_peer_data = get_other_peer_data(peer_data);
4702 if (other_peer_data->channel_handles) {
4703 ssh_channel_info_t *peer_channel = wmem_map_lookup(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel));
4704 if (peer_channel) {
4705 new_channel->handle = peer_channel->handle;
4710 static ssh_channel_info_t*
4711 get_channel_info_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel)
4713 if (peer_data->channel_handles == NULL) {
4714 return NULL;
4716 ssh_channel_info_t *channel = wmem_map_lookup(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel));
4718 return channel;
4721 static void
4722 set_subdissector_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, const uint8_t* subsystem_name)
4724 dissector_handle_t handle = NULL;
4725 if(0 == strcmp(subsystem_name, "sftp")) {
4726 handle = sftp_handle;
4729 if (handle) {
4730 /* Map this handle to the recipient channel */
4731 ssh_channel_info_t *channel = NULL;
4732 if (peer_data->channel_handles == NULL) {
4733 peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
4734 } else {
4735 channel = wmem_map_lookup(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel));
4737 if (channel == NULL) {
4738 channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t);
4739 channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
4740 wmem_map_insert(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel), channel);
4742 channel->handle = handle;
4744 /* This recipient channel is the sender channel for the other side.
4745 * Do we know what the recipient channel on the other side is? */
4746 struct ssh_peer_data *other_peer_data = get_other_peer_data(peer_data);
4748 wmem_map_t *channel_info = other_peer_data->channel_info;
4749 if (channel_info) {
4750 uint32_t sender_channel;
4751 if (wmem_map_lookup_extended(channel_info, GUINT_TO_POINTER(recipient_channel), NULL, (void**)&sender_channel)) {
4752 /* Yes. See the handle for the other side too. */
4753 if (other_peer_data->channel_handles == NULL) {
4754 other_peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
4755 channel = NULL;
4756 } else {
4757 channel = wmem_map_lookup(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel));
4759 if (channel == NULL) {
4760 channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t);
4761 channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
4762 wmem_map_insert(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel), channel);
4764 channel->handle = handle;
4770 /* Channel mapping. }}} */
4772 static int
4773 ssh_dissect_connection_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
4774 int offset, proto_item *msg_type_tree, unsigned msg_code)
4776 (void)pinfo;
4777 if(msg_code==SSH_MSG_GLOBAL_REQUEST){
4778 uint8_t* request_name;
4779 unsigned slen;
4780 slen = tvb_get_ntohl(packet_tvb, offset) ;
4781 proto_tree_add_item(msg_type_tree, hf_ssh_global_request_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4782 offset += 4;
4783 request_name = tvb_get_string_enc(pinfo->pool, packet_tvb, offset, slen, ENC_ASCII|ENC_NA);
4784 proto_tree_add_item(msg_type_tree, hf_ssh_global_request_name, packet_tvb, offset, slen, ENC_ASCII);
4785 offset += slen;
4786 proto_tree_add_item(msg_type_tree, hf_ssh_global_request_want_reply, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4787 offset += 1;
4788 if (0 == strcmp(request_name, "hostkeys-00@openssh.com")) {
4789 unsigned alen;
4790 proto_item *ti;
4791 int dissected_len = 0;
4792 alen = tvb_get_ntohl(packet_tvb, offset) ;
4793 ti = proto_tree_add_item(msg_type_tree, hf_ssh_global_request_hostkeys_array_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4794 offset += 4;
4795 proto_item *blob_tree = NULL;
4796 blob_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, alen, ett_userauth_pk_blob, NULL, "Public key blob");
4797 dissected_len = ssh_dissect_public_key_blob(packet_tvb, pinfo, offset, blob_tree) - offset;
4798 if(dissected_len!=(int)alen){
4799 expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, alen);
4801 offset += alen;
4804 return offset;
4807 static int
4808 ssh_dissect_local_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
4809 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code) {
4810 unsigned slen;
4811 if (peer_data->global_data->ext_ping_openssh_offered && msg_code >= SSH_MSG_PING && msg_code <= SSH_MSG_PONG) {
4812 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_ext_ping_msg_vals, "Unknown (%u)"));
4813 proto_tree_add_item(msg_type_tree, hf_ssh2_ext_ping_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4814 offset += 1;
4815 if (msg_code == SSH_MSG_PING) {
4816 slen = tvb_get_ntohl(packet_tvb, offset) ;
4817 proto_tree_add_item(msg_type_tree, hf_ssh_ping_data_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4818 offset += 4;
4819 proto_tree_add_item(msg_type_tree, hf_ssh_ping_data, packet_tvb, offset, slen, ENC_NA);
4820 offset += slen;
4821 } else if (msg_code == SSH_MSG_PONG) {
4822 slen = tvb_get_ntohl(packet_tvb, offset) ;
4823 proto_tree_add_item(msg_type_tree, hf_ssh_pong_data_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4824 offset += 4;
4825 proto_tree_add_item(msg_type_tree, hf_ssh_pong_data, packet_tvb, offset, slen, ENC_NA);
4826 offset += slen;
4828 } else {
4829 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
4830 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4831 offset += 1;
4833 return offset;
4836 static int
4837 ssh_dissect_public_key_blob(tvbuff_t *packet_tvb, packet_info *pinfo,
4838 int offset, proto_item *msg_type_tree)
4840 (void)pinfo;
4841 unsigned slen;
4842 slen = tvb_get_ntohl(packet_tvb, offset) ;
4843 proto_tree_add_item(msg_type_tree, hf_ssh_pk_blob_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4844 offset += 4;
4845 proto_tree_add_item(msg_type_tree, hf_ssh_pk_blob_name, packet_tvb, offset, slen, ENC_ASCII);
4846 offset += slen;
4847 offset += ssh_tree_add_mpint(packet_tvb, offset, msg_type_tree, hf_ssh_blob_e);
4848 offset += ssh_tree_add_mpint(packet_tvb, offset, msg_type_tree, hf_ssh_blob_p);
4849 return offset;
4852 static int
4853 ssh_dissect_public_key_signature(tvbuff_t *packet_tvb, packet_info *pinfo,
4854 int offset, proto_item *msg_type_tree)
4856 (void)pinfo;
4857 unsigned slen;
4858 slen = tvb_get_ntohl(packet_tvb, offset) ;
4859 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_blob_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4860 offset += 4;
4861 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_blob_name, packet_tvb, offset, slen, ENC_ASCII);
4862 offset += slen;
4863 slen = tvb_get_ntohl(packet_tvb, offset) ;
4864 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_s_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4865 offset += 4;
4866 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_s, packet_tvb, offset, slen, ENC_NA);
4867 offset += slen;
4868 return offset;
4871 #ifdef SSH_DECRYPT_DEBUG /* {{{ */
4873 static FILE* ssh_debug_file;
4875 static void
4876 ssh_prefs_apply_cb(void)
4878 ssh_set_debug(ssh_debug_file_name);
4881 static void
4882 ssh_set_debug(const char* name)
4884 static int debug_file_must_be_closed;
4885 int use_stderr;
4887 use_stderr = name?(strcmp(name, SSH_DEBUG_USE_STDERR) == 0):0;
4889 if (debug_file_must_be_closed)
4890 fclose(ssh_debug_file);
4892 if (use_stderr)
4893 ssh_debug_file = stderr;
4894 else if (!name || (strcmp(name, "") ==0))
4895 ssh_debug_file = NULL;
4896 else
4897 ssh_debug_file = ws_fopen(name, "w");
4899 if (!use_stderr && ssh_debug_file)
4900 debug_file_must_be_closed = 1;
4901 else
4902 debug_file_must_be_closed = 0;
4904 ssh_debug_printf("Wireshark SSH debug log \n\n");
4905 #ifdef HAVE_LIBGNUTLS
4906 ssh_debug_printf("GnuTLS version: %s\n", gnutls_check_version(NULL));
4907 #endif
4908 ssh_debug_printf("Libgcrypt version: %s\n", gcry_check_version(NULL));
4909 ssh_debug_printf("\n");
4912 static void
4913 ssh_debug_flush(void)
4915 if (ssh_debug_file)
4916 fflush(ssh_debug_file);
4919 static void
4920 ssh_debug_printf(const char* fmt, ...)
4922 va_list ap;
4924 if (!ssh_debug_file)
4925 return;
4927 va_start(ap, fmt);
4928 vfprintf(ssh_debug_file, fmt, ap);
4929 va_end(ap);
4932 static void
4933 ssh_print_data(const char* name, const unsigned char* data, size_t len)
4935 size_t i, j, k;
4936 if (!ssh_debug_file)
4937 return;
4938 #ifdef OPENSSH_STYLE
4939 fprintf(ssh_debug_file,"%s[%d]\n",name, (int) len);
4940 #else
4941 fprintf(ssh_debug_file,"%s[%d]:\n",name, (int) len);
4942 #endif
4943 for (i=0; i<len; i+=16) {
4944 #ifdef OPENSSH_STYLE
4945 fprintf(ssh_debug_file,"%04u: ", (unsigned int)i);
4946 #else
4947 fprintf(ssh_debug_file,"| ");
4948 #endif
4949 for (j=i, k=0; k<16 && j<len; ++j, ++k)
4950 fprintf(ssh_debug_file,"%.2x ",data[j]);
4951 for (; k<16; ++k)
4952 fprintf(ssh_debug_file," ");
4953 #ifdef OPENSSH_STYLE
4954 fputc(' ', ssh_debug_file);
4955 #else
4956 fputc('|', ssh_debug_file);
4957 #endif
4958 for (j=i, k=0; k<16 && j<len; ++j, ++k) {
4959 unsigned char c = data[j];
4960 if (!g_ascii_isprint(c) || (c=='\t')) c = '.';
4961 fputc(c, ssh_debug_file);
4963 #ifdef OPENSSH_STYLE
4964 fprintf(ssh_debug_file,"\n");
4965 #else
4966 for (; k<16; ++k)
4967 fputc(' ', ssh_debug_file);
4968 fprintf(ssh_debug_file,"|\n");
4969 #endif
4973 #endif /* SSH_DECRYPT_DEBUG }}} */
4975 static void
4976 ssh_secrets_block_callback(const void *secrets, unsigned size)
4978 ssh_keylog_process_lines((const uint8_t *)secrets, size);
4981 /* Functions for SSH random hashtables. {{{ */
4982 static int
4983 ssh_equal (const void *v, const void *v2)
4985 if (v == NULL || v2 == NULL) {
4986 return 0;
4989 const ssh_bignum *val1;
4990 const ssh_bignum *val2;
4991 val1 = (const ssh_bignum *)v;
4992 val2 = (const ssh_bignum *)v2;
4994 if (val1->length == val2->length &&
4995 !memcmp(val1->data, val2->data, val2->length)) {
4996 return 1;
4998 return 0;
5001 static unsigned
5002 ssh_hash (const void *v)
5004 unsigned l,hash;
5005 const ssh_bignum* id;
5006 const unsigned* cur;
5008 if (v == NULL) {
5009 return 0;
5012 hash = 0;
5013 id = (const ssh_bignum*) v;
5015 /* id and id->data are mallocated in ssh_save_master_key(). As such 'data'
5016 * should be aligned for any kind of access (for example as a unsigned as
5017 * is done below). The intermediate void* cast is to prevent "cast
5018 * increases required alignment of target type" warnings on CPUs (such
5019 * as SPARCs) that do not allow misaligned memory accesses.
5021 cur = (const unsigned*)(void*) id->data;
5023 for (l=4; (l < id->length); l+=4, cur++)
5024 hash = hash ^ (*cur);
5026 return hash;
5029 static void
5030 ssh_free_glib_allocated_bignum(void *data)
5032 ssh_bignum * bignum;
5033 if (data == NULL) {
5034 return;
5037 bignum = (ssh_bignum *) data;
5038 g_free(bignum->data);
5039 g_free(bignum);
5042 static void
5043 ssh_free_glib_allocated_entry(void *data)
5045 ssh_key_map_entry_t * entry;
5046 if (data == NULL) {
5047 return;
5050 entry = (ssh_key_map_entry_t *) data;
5051 g_free(entry->type);
5052 ssh_free_glib_allocated_bignum(entry->key_material);
5053 g_free(entry);
5055 /* Functions for SSH random hashtables. }}} */
5057 static void
5058 ssh_shutdown(void) {
5059 g_hash_table_destroy(ssh_master_key_map);
5062 void
5063 proto_register_ssh(void)
5065 static hf_register_info hf[] = {
5066 { &hf_ssh_protocol,
5067 { "Protocol", "ssh.protocol",
5068 FT_STRING, BASE_NONE, NULL, 0x0,
5069 NULL, HFILL }},
5071 { &hf_ssh_packet_length,
5072 { "Packet Length", "ssh.packet_length",
5073 FT_UINT32, BASE_DEC, NULL, 0x0,
5074 NULL, HFILL }},
5076 { &hf_ssh_packet_length_encrypted,
5077 { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
5078 FT_BYTES, BASE_NONE, NULL, 0x0,
5079 NULL, HFILL }},
5081 { &hf_ssh_padding_length,
5082 { "Padding Length", "ssh.padding_length",
5083 FT_UINT8, BASE_DEC, NULL, 0x0,
5084 NULL, HFILL }},
5086 { &hf_ssh_payload,
5087 { "Payload", "ssh.payload",
5088 FT_BYTES, BASE_NONE, NULL, 0x0,
5089 NULL, HFILL }},
5091 { &hf_ssh_encrypted_packet,
5092 { "Encrypted Packet", "ssh.encrypted_packet",
5093 FT_BYTES, BASE_NONE, NULL, 0x0,
5094 NULL, HFILL }},
5096 { &hf_ssh_padding_string,
5097 { "Padding String", "ssh.padding_string",
5098 FT_BYTES, BASE_NONE, NULL, 0x0,
5099 NULL, HFILL }},
5101 { &hf_ssh_seq_num,
5102 { "Sequence number", "ssh.seq_num",
5103 FT_UINT32, BASE_DEC, NULL, 0x0,
5104 NULL, HFILL }},
5106 { &hf_ssh_mac_string,
5107 { "MAC", "ssh.mac",
5108 FT_BYTES, BASE_NONE, NULL, 0x0,
5109 "Message authentication code", HFILL }},
5111 { &hf_ssh_mac_status,
5112 { "MAC Status", "ssh.mac.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
5113 NULL, HFILL }},
5115 { &hf_ssh_direction,
5116 { "Direction", "ssh.direction",
5117 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5118 "Message direction", HFILL }},
5120 { &hf_ssh_msg_code,
5121 { "Message Code", "ssh.message_code",
5122 FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
5123 NULL, HFILL }},
5125 { &hf_ssh2_msg_code,
5126 { "Message Code", "ssh.message_code",
5127 FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
5128 NULL, HFILL }},
5130 { &hf_ssh2_kex_dh_msg_code,
5131 { "Message Code", "ssh.message_code",
5132 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
5133 NULL, HFILL }},
5135 { &hf_ssh2_kex_dh_gex_msg_code,
5136 { "Message Code", "ssh.message_code",
5137 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
5138 NULL, HFILL }},
5140 { &hf_ssh2_kex_ecdh_msg_code,
5141 { "Message Code", "ssh.message_code",
5142 FT_UINT8, BASE_DEC, VALS(ssh2_kex_ecdh_msg_vals), 0x0,
5143 NULL, HFILL }},
5145 { &hf_ssh2_ext_ping_msg_code,
5146 { "Message Code", "ssh.message_code",
5147 FT_UINT8, BASE_DEC, VALS(ssh2_ext_ping_msg_vals), 0x0,
5148 NULL, HFILL }},
5150 { &hf_ssh_cookie,
5151 { "Cookie", "ssh.cookie",
5152 FT_BYTES, BASE_NONE, NULL, 0x0,
5153 NULL, HFILL }},
5155 { &hf_ssh_kex_algorithms,
5156 { "kex_algorithms string", "ssh.kex_algorithms",
5157 FT_STRING, BASE_NONE, NULL, 0x0,
5158 NULL, HFILL }},
5160 { &hf_ssh_server_host_key_algorithms,
5161 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
5162 FT_STRING, BASE_NONE, NULL, 0x0,
5163 NULL, HFILL }},
5165 { &hf_ssh_encryption_algorithms_client_to_server,
5166 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
5167 FT_STRING, BASE_NONE, NULL, 0x0,
5168 NULL, HFILL }},
5170 { &hf_ssh_encryption_algorithms_server_to_client,
5171 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
5172 FT_STRING, BASE_NONE, NULL, 0x0,
5173 NULL, HFILL }},
5175 { &hf_ssh_mac_algorithms_client_to_server,
5176 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
5177 FT_STRING, BASE_NONE, NULL, 0x0,
5178 NULL, HFILL }},
5180 { &hf_ssh_mac_algorithms_server_to_client,
5181 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
5182 FT_STRING, BASE_NONE, NULL, 0x0,
5183 NULL, HFILL }},
5185 { &hf_ssh_compression_algorithms_client_to_server,
5186 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
5187 FT_STRING, BASE_NONE, NULL, 0x0,
5188 NULL, HFILL }},
5190 { &hf_ssh_compression_algorithms_server_to_client,
5191 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
5192 FT_STRING, BASE_NONE, NULL, 0x0,
5193 NULL, HFILL }},
5195 { &hf_ssh_languages_client_to_server,
5196 { "languages_client_to_server string", "ssh.languages_client_to_server",
5197 FT_STRING, BASE_NONE, NULL, 0x0,
5198 NULL, HFILL }},
5200 { &hf_ssh_languages_server_to_client,
5201 { "languages_server_to_client string", "ssh.languages_server_to_client",
5202 FT_STRING, BASE_NONE, NULL, 0x0,
5203 NULL, HFILL }},
5205 { &hf_ssh_kex_algorithms_length,
5206 { "kex_algorithms length", "ssh.kex_algorithms_length",
5207 FT_UINT32, BASE_DEC, NULL, 0x0,
5208 NULL, HFILL }},
5210 { &hf_ssh_server_host_key_algorithms_length,
5211 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
5212 FT_UINT32, BASE_DEC, NULL, 0x0,
5213 NULL, HFILL }},
5215 { &hf_ssh_encryption_algorithms_client_to_server_length,
5216 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
5217 FT_UINT32, BASE_DEC, NULL, 0x0,
5218 NULL, HFILL }},
5220 { &hf_ssh_encryption_algorithms_server_to_client_length,
5221 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
5222 FT_UINT32, BASE_DEC, NULL, 0x0,
5223 NULL, HFILL }},
5225 { &hf_ssh_mac_algorithms_client_to_server_length,
5226 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
5227 FT_UINT32, BASE_DEC, NULL, 0x0,
5228 NULL, HFILL }},
5230 { &hf_ssh_mac_algorithms_server_to_client_length,
5231 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
5232 FT_UINT32, BASE_DEC, NULL, 0x0,
5233 NULL, HFILL }},
5235 { &hf_ssh_compression_algorithms_client_to_server_length,
5236 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
5237 FT_UINT32, BASE_DEC, NULL, 0x0,
5238 NULL, HFILL }},
5240 { &hf_ssh_compression_algorithms_server_to_client_length,
5241 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
5242 FT_UINT32, BASE_DEC, NULL, 0x0,
5243 NULL, HFILL }},
5245 { &hf_ssh_languages_client_to_server_length,
5246 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
5247 FT_UINT32, BASE_DEC, NULL, 0x0,
5248 NULL, HFILL }},
5250 { &hf_ssh_languages_server_to_client_length,
5251 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
5252 FT_UINT32, BASE_DEC, NULL, 0x0,
5253 NULL, HFILL }},
5255 { &hf_ssh_first_kex_packet_follows,
5256 { "First KEX Packet Follows", "ssh.first_kex_packet_follows",
5257 FT_UINT8, BASE_DEC, NULL, 0x0,
5258 NULL, HFILL }},
5260 { &hf_ssh_kex_reserved,
5261 { "Reserved", "ssh.kex.reserved",
5262 FT_BYTES, BASE_NONE, NULL, 0x0,
5263 NULL, HFILL }},
5265 { &hf_ssh_kex_hassh_algo,
5266 { "hasshAlgorithms", "ssh.kex.hassh_algorithms",
5267 FT_STRING, BASE_NONE, NULL, 0x0,
5268 NULL, HFILL }},
5270 { &hf_ssh_kex_hassh,
5271 { "hassh", "ssh.kex.hassh",
5272 FT_STRING, BASE_NONE, NULL, 0x0,
5273 NULL, HFILL }},
5275 { &hf_ssh_kex_hasshserver_algo,
5276 { "hasshServerAlgorithms", "ssh.kex.hasshserver_algorithms",
5277 FT_STRING, BASE_NONE, NULL, 0x0,
5278 NULL, HFILL }},
5280 { &hf_ssh_kex_hasshserver,
5281 { "hasshServer", "ssh.kex.hasshserver",
5282 FT_STRING, BASE_NONE, NULL, 0x0,
5283 NULL, HFILL }},
5285 { &hf_ssh_hostkey_length,
5286 { "Host key length", "ssh.host_key.length",
5287 FT_UINT32, BASE_DEC, NULL, 0x0,
5288 NULL, HFILL }},
5290 { &hf_ssh_hostkey_type_length,
5291 { "Host key type length", "ssh.host_key.type_length",
5292 FT_UINT32, BASE_DEC, NULL, 0x0,
5293 NULL, HFILL }},
5295 { &hf_ssh_hostkey_type,
5296 { "Host key type", "ssh.host_key.type",
5297 FT_STRING, BASE_NONE, NULL, 0x0,
5298 NULL, HFILL }},
5300 { &hf_ssh_hostkey_data,
5301 { "Host key data", "ssh.host_key.data",
5302 FT_BYTES, BASE_NONE, NULL, 0x0,
5303 NULL, HFILL }},
5305 { &hf_ssh_hostkey_rsa_n,
5306 { "RSA modulus (N)", "ssh.host_key.rsa.n",
5307 FT_BYTES, BASE_NONE, NULL, 0x0,
5308 NULL, HFILL }},
5310 { &hf_ssh_hostkey_rsa_e,
5311 { "RSA public exponent (e)", "ssh.host_key.rsa.e",
5312 FT_BYTES, BASE_NONE, NULL, 0x0,
5313 NULL, HFILL }},
5315 { &hf_ssh_hostkey_dsa_p,
5316 { "DSA prime modulus (p)", "ssh.host_key.dsa.p",
5317 FT_BYTES, BASE_NONE, NULL, 0x0,
5318 NULL, HFILL }},
5320 { &hf_ssh_hostkey_dsa_q,
5321 { "DSA prime divisor (q)", "ssh.host_key.dsa.q",
5322 FT_BYTES, BASE_NONE, NULL, 0x0,
5323 NULL, HFILL }},
5325 { &hf_ssh_hostkey_dsa_g,
5326 { "DSA subgroup generator (g)", "ssh.host_key.dsa.g",
5327 FT_BYTES, BASE_NONE, NULL, 0x0,
5328 NULL, HFILL }},
5330 { &hf_ssh_hostkey_dsa_y,
5331 { "DSA public key (y)", "ssh.host_key.dsa.y",
5332 FT_BYTES, BASE_NONE, NULL, 0x0,
5333 NULL, HFILL }},
5335 { &hf_ssh_hostkey_ecdsa_curve_id,
5336 { "ECDSA elliptic curve identifier", "ssh.host_key.ecdsa.id",
5337 FT_STRING, BASE_NONE, NULL, 0x0,
5338 NULL, HFILL }},
5340 { &hf_ssh_hostkey_ecdsa_curve_id_length,
5341 { "ECDSA elliptic curve identifier length", "ssh.host_key.ecdsa.id_length",
5342 FT_UINT32, BASE_DEC, NULL, 0x0,
5343 NULL, HFILL }},
5345 { &hf_ssh_hostkey_ecdsa_q,
5346 { "ECDSA public key (Q)", "ssh.host_key.ecdsa.q",
5347 FT_BYTES, BASE_NONE, NULL, 0x0,
5348 NULL, HFILL }},
5350 { &hf_ssh_hostkey_ecdsa_q_length,
5351 { "ECDSA public key length", "ssh.host_key.ecdsa.q_length",
5352 FT_UINT32, BASE_DEC, NULL, 0x0,
5353 NULL, HFILL }},
5355 { &hf_ssh_hostkey_eddsa_key,
5356 { "EdDSA public key", "ssh.host_key.eddsa.key",
5357 FT_BYTES, BASE_NONE, NULL, 0x0,
5358 NULL, HFILL }},
5360 { &hf_ssh_hostkey_eddsa_key_length,
5361 { "EdDSA public key length", "ssh.host_key.eddsa.key_length",
5362 FT_UINT32, BASE_DEC, NULL, 0x0,
5363 NULL, HFILL }},
5365 { &hf_ssh_hostsig_length,
5366 { "Host signature length", "ssh.host_sig.length",
5367 FT_UINT32, BASE_DEC, NULL, 0x0,
5368 NULL, HFILL }},
5370 { &hf_ssh_hostsig_type_length,
5371 { "Host signature type length", "ssh.host_sig.type_length",
5372 FT_UINT32, BASE_DEC, NULL, 0x0,
5373 NULL, HFILL }},
5375 { &hf_ssh_hostsig_type,
5376 { "Host signature type", "ssh.host_sig.type",
5377 FT_STRING, BASE_NONE, NULL, 0x0,
5378 NULL, HFILL }},
5380 { &hf_ssh_hostsig_data,
5381 { "Host signature data", "ssh.host_sig.data",
5382 FT_BYTES, BASE_NONE, NULL, 0x0,
5383 NULL, HFILL }},
5385 { &hf_ssh_hostsig_rsa,
5386 { "RSA signature", "ssh.host_sig.rsa",
5387 FT_BYTES, BASE_NONE, NULL, 0x0,
5388 NULL, HFILL }},
5390 { &hf_ssh_hostsig_dsa,
5391 { "DSA signature", "ssh.host_sig.dsa",
5392 FT_BYTES, BASE_NONE, NULL, 0x0,
5393 NULL, HFILL }},
5395 { &hf_ssh_dh_e,
5396 { "DH client e", "ssh.dh.e",
5397 FT_BYTES, BASE_NONE, NULL, 0x0,
5398 NULL, HFILL }},
5400 { &hf_ssh_dh_f,
5401 { "DH server f", "ssh.dh.f",
5402 FT_BYTES, BASE_NONE, NULL, 0x0,
5403 NULL, HFILL }},
5405 { &hf_ssh_dh_gex_min,
5406 { "DH GEX Min", "ssh.dh_gex.min",
5407 FT_UINT32, BASE_DEC, NULL, 0x0,
5408 "Minimal acceptable group size", HFILL }},
5410 { &hf_ssh_dh_gex_nbits,
5411 { "DH GEX Number of Bits", "ssh.dh_gex.nbits",
5412 FT_UINT32, BASE_DEC, NULL, 0x0,
5413 "Preferred group size", HFILL }},
5415 { &hf_ssh_dh_gex_max,
5416 { "DH GEX Max", "ssh.dh_gex.max",
5417 FT_UINT32, BASE_DEC, NULL, 0x0,
5418 "Maximal acceptable group size", HFILL }},
5420 { &hf_ssh_dh_gex_p,
5421 { "DH GEX modulus (P)", "ssh.dh_gex.p",
5422 FT_BYTES, BASE_NONE, NULL, 0x0,
5423 NULL, HFILL }},
5425 { &hf_ssh_dh_gex_g,
5426 { "DH GEX base (G)", "ssh.dh_gex.g",
5427 FT_BYTES, BASE_NONE, NULL, 0x0,
5428 NULL, HFILL }},
5430 { &hf_ssh_ecdh_q_c,
5431 { "ECDH client's ephemeral public key (Q_C)", "ssh.ecdh.q_c",
5432 FT_BYTES, BASE_NONE, NULL, 0x0,
5433 NULL, HFILL }},
5435 { &hf_ssh_ecdh_q_c_length,
5436 { "ECDH client's ephemeral public key length", "ssh.ecdh.q_c_length",
5437 FT_UINT32, BASE_DEC, NULL, 0x0,
5438 NULL, HFILL }},
5440 { &hf_ssh_ecdh_q_s,
5441 { "ECDH server's ephemeral public key (Q_S)", "ssh.ecdh.q_s",
5442 FT_BYTES, BASE_NONE, NULL, 0x0,
5443 NULL, HFILL }},
5445 { &hf_ssh_ecdh_q_s_length,
5446 { "ECDH server's ephemeral public key length", "ssh.ecdh.q_s_length",
5447 FT_UINT32, BASE_DEC, NULL, 0x0,
5448 NULL, HFILL }},
5450 { &hf_ssh_mpint_length,
5451 { "Multi Precision Integer Length", "ssh.mpint_length",
5452 FT_UINT32, BASE_DEC, NULL, 0x0,
5453 NULL, HFILL }},
5455 { &hf_ssh_ignore_data_length,
5456 { "Debug message length", "ssh.ignore_data_length",
5457 FT_UINT32, BASE_DEC, NULL, 0x0,
5458 NULL, HFILL }},
5460 { &hf_ssh_ignore_data,
5461 { "Ignore data", "ssh.ignore_data",
5462 FT_BYTES, BASE_NONE, NULL, 0x0,
5463 NULL, HFILL }},
5465 { &hf_ssh_debug_always_display,
5466 { "Always Display", "ssh.debug_always_display",
5467 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5468 NULL, HFILL }},
5470 { &hf_ssh_debug_message_length,
5471 { "Debug message length", "ssh.debug_name_length",
5472 FT_UINT32, BASE_DEC, NULL, 0x0,
5473 NULL, HFILL }},
5475 { &hf_ssh_debug_message,
5476 { "Debug message", "ssh.debug_name",
5477 FT_STRING, BASE_NONE, NULL, 0x0,
5478 NULL, HFILL }},
5480 { &hf_ssh_service_name_length,
5481 { "Service Name length", "ssh.service_name_length",
5482 FT_UINT32, BASE_DEC, NULL, 0x0,
5483 NULL, HFILL }},
5485 { &hf_ssh_service_name,
5486 { "Service Name", "ssh.service_name",
5487 FT_STRING, BASE_NONE, NULL, 0x0,
5488 NULL, HFILL }},
5490 { &hf_ssh_disconnect_reason,
5491 { "Disconnect reason", "ssh.disconnect_reason",
5492 FT_UINT32, BASE_HEX, NULL, 0x0,
5493 NULL, HFILL }},
5495 { &hf_ssh_disconnect_description_length,
5496 { "Disconnect description length", "ssh.disconnect_description_length",
5497 FT_UINT32, BASE_DEC, NULL, 0x0,
5498 NULL, HFILL }},
5500 { &hf_ssh_disconnect_description,
5501 { "Disconnect description", "ssh.disconnect_description",
5502 FT_STRING, BASE_NONE, NULL, 0x0,
5503 NULL, HFILL }},
5505 { &hf_ssh_ext_count,
5506 { "Extension count", "ssh.extension.count",
5507 FT_UINT32, BASE_DEC, NULL, 0x0,
5508 NULL, HFILL }},
5510 { &hf_ssh_ext_name_length,
5511 { "Extension name length", "ssh.extension.name_length",
5512 FT_UINT32, BASE_DEC, NULL, 0x0,
5513 NULL, HFILL }},
5515 { &hf_ssh_ext_name,
5516 { "Extension name", "ssh.extension.name",
5517 FT_STRING, BASE_NONE, NULL, 0x0,
5518 NULL, HFILL }},
5520 { &hf_ssh_ext_value_length,
5521 { "Extension value length", "ssh.extension.value_length",
5522 FT_UINT32, BASE_DEC, NULL, 0x0,
5523 NULL, HFILL }},
5525 { &hf_ssh_ext_value,
5526 { "Extension value", "ssh.extension.value",
5527 FT_BYTES, BASE_NONE, NULL, 0x0,
5528 NULL, HFILL }},
5530 { &hf_ssh_ext_server_sig_algs_algorithms,
5531 { "Accepted signature algorithms", "ssh.extension.server_sig_algs.algorithms",
5532 FT_STRING, BASE_NONE, NULL, 0x0,
5533 NULL, HFILL }},
5535 { &hf_ssh_ext_delay_compression_algorithms_client_to_server_length,
5536 { "Compression algorithms (client to server) length", "ssh.extension.delay_compression.compression_algorithms_client_to_server_length",
5537 FT_UINT32, BASE_DEC, NULL, 0x0,
5538 NULL, HFILL }},
5540 { &hf_ssh_ext_delay_compression_algorithms_client_to_server,
5541 { "Compression algorithms (client to server)", "ssh.extension.delay_compression.compression_algorithms_client_to_server",
5542 FT_STRING, BASE_NONE, NULL, 0x0,
5543 NULL, HFILL }},
5545 { &hf_ssh_ext_delay_compression_algorithms_server_to_client_length,
5546 { "Compression algorithms (server to client) length", "ssh.extension.delay_compression.compression_algorithms_server_to_client_length",
5547 FT_UINT32, BASE_DEC, NULL, 0x0,
5548 NULL, HFILL }},
5550 { &hf_ssh_ext_delay_compression_algorithms_server_to_client,
5551 { "Compression algorithms (server to client)", "ssh.extension.delay_compression.compression_algorithms_server_to_client",
5552 FT_STRING, BASE_NONE, NULL, 0x0,
5553 NULL, HFILL }},
5555 { &hf_ssh_ext_no_flow_control_value,
5556 { "No flow control flag", "ssh.extension.no_flow_control.value",
5557 FT_STRING, BASE_NONE, NULL, 0x0,
5558 NULL, HFILL }},
5560 { &hf_ssh_ext_elevation_value,
5561 { "Elevation flag", "ssh.extension.elevation.value",
5562 FT_STRING, BASE_NONE, NULL, 0x0,
5563 NULL, HFILL }},
5565 { &hf_ssh_ext_prop_publickey_algorithms_algorithms,
5566 { "Public key algorithms", "ssh.extension.prop_publickey_algorithms.algorithms",
5567 FT_STRING, BASE_NONE, NULL, 0x0,
5568 NULL, HFILL }},
5570 { &hf_ssh_lang_tag_length,
5571 { "Language tag length", "ssh.lang_tag_length",
5572 FT_UINT32, BASE_DEC, NULL, 0x0,
5573 NULL, HFILL }},
5575 { &hf_ssh_lang_tag,
5576 { "Language tag", "ssh.lang_tag",
5577 FT_STRING, BASE_NONE, NULL, 0x0,
5578 NULL, HFILL }},
5580 { &hf_ssh_ping_data_length,
5581 { "Data length", "ssh.ping_data_length",
5582 FT_UINT32, BASE_DEC, NULL, 0x0,
5583 NULL, HFILL }},
5585 { &hf_ssh_ping_data,
5586 { "Data", "ssh.ping_data",
5587 FT_BYTES, BASE_NONE, NULL, 0x0,
5588 NULL, HFILL }},
5590 { &hf_ssh_pong_data_length,
5591 { "Data length", "ssh.pong_data_length",
5592 FT_UINT32, BASE_DEC, NULL, 0x0,
5593 NULL, HFILL }},
5595 { &hf_ssh_pong_data,
5596 { "Data", "ssh.pong_data",
5597 FT_BYTES, BASE_NONE, NULL, 0x0,
5598 NULL, HFILL }},
5601 { &hf_ssh_userauth_user_name_length,
5602 { "User Name length", "ssh.userauth_user_name_length",
5603 FT_UINT32, BASE_DEC, NULL, 0x0,
5604 NULL, HFILL }},
5606 { &hf_ssh_userauth_user_name,
5607 { "User Name", "ssh.userauth_user_name",
5608 FT_STRING, BASE_NONE, NULL, 0x0,
5609 NULL, HFILL }},
5611 { &hf_ssh_userauth_change_password,
5612 { "Change password", "ssh.userauth.change_password",
5613 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5614 NULL, HFILL }},
5616 { &hf_ssh_userauth_service_name_length,
5617 { "Service Name length", "ssh.userauth_service_name_length",
5618 FT_UINT32, BASE_DEC, NULL, 0x0,
5619 NULL, HFILL }},
5621 { &hf_ssh_userauth_service_name,
5622 { "Service Name", "ssh.userauth_service_name",
5623 FT_STRING, BASE_NONE, NULL, 0x0,
5624 NULL, HFILL }},
5626 { &hf_ssh_userauth_method_name_length,
5627 { "Method Name length", "ssh.userauth_method_name_length",
5628 FT_UINT32, BASE_DEC, NULL, 0x0,
5629 NULL, HFILL }},
5631 { &hf_ssh_userauth_method_name,
5632 { "Method Name", "ssh.userauth_method_name",
5633 FT_STRING, BASE_NONE, NULL, 0x0,
5634 NULL, HFILL }},
5636 { &hf_ssh_userauth_have_signature,
5637 { "Have signature", "ssh.userauth.have_signature",
5638 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5639 NULL, HFILL }},
5641 { &hf_ssh_userauth_password_length,
5642 { "Password length", "ssh.userauth_password_length",
5643 FT_UINT32, BASE_DEC, NULL, 0x0,
5644 NULL, HFILL }},
5646 { &hf_ssh_userauth_password,
5647 { "Password", "ssh.userauth_password",
5648 FT_STRING, BASE_NONE, NULL, 0x0,
5649 NULL, HFILL }},
5651 { &hf_ssh_userauth_new_password_length,
5652 { "New password length", "ssh.userauth_new_password_length",
5653 FT_UINT32, BASE_DEC, NULL, 0x0,
5654 NULL, HFILL }},
5656 { &hf_ssh_userauth_new_password,
5657 { "New password", "ssh.userauth_new_password",
5658 FT_STRING, BASE_NONE, NULL, 0x0,
5659 NULL, HFILL }},
5661 { &hf_ssh_auth_failure_list_length,
5662 { "Authentications that can continue list len", "ssh.auth_failure_cont_list_length",
5663 FT_UINT32, BASE_DEC, NULL, 0x0,
5664 NULL, HFILL }},
5666 { &hf_ssh_auth_failure_list,
5667 { "Authentications that can continue list", "ssh.auth_failure_cont_list",
5668 FT_STRING, BASE_NONE, NULL, 0x0,
5669 NULL, HFILL }},
5671 { &hf_ssh_userauth_partial_success,
5672 { "Partial success", "ssh.userauth.partial_success",
5673 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5674 NULL, HFILL }},
5676 { &hf_ssh_userauth_pka_name_len,
5677 { "Public key algorithm name length", "ssh.userauth_pka_name_length",
5678 FT_UINT32, BASE_DEC, NULL, 0x0,
5679 NULL, HFILL }},
5681 { &hf_ssh_userauth_pka_name,
5682 { "Public key algorithm name", "ssh.userauth_pka_name",
5683 FT_STRING, BASE_NONE, NULL, 0x0,
5684 NULL, HFILL }},
5686 { &hf_ssh_pk_blob_name_length,
5687 { "Public key blob algorithm name length", "ssh.pk_blob_name_length",
5688 FT_UINT32, BASE_DEC, NULL, 0x0,
5689 NULL, HFILL }},
5691 { &hf_ssh_pk_blob_name,
5692 { "Public key blob algorithm name", "ssh.pk_blob_name",
5693 FT_STRING, BASE_NONE, NULL, 0x0,
5694 NULL, HFILL }},
5696 { &hf_ssh_blob_length,
5697 { "Public key blob length", "ssh.pk_blob_length",
5698 FT_UINT32, BASE_DEC, NULL, 0x0,
5699 NULL, HFILL }},
5701 { &hf_ssh_blob_p,
5702 { "ssh-rsa modulus (n)", "ssh.blob.ssh-rsa.n",
5703 FT_BYTES, BASE_NONE, NULL, 0x0,
5704 NULL, HFILL }},
5706 { &hf_ssh_blob_e,
5707 { "ssh-rsa public exponent (e)", "ssh.blob.ssh-rsa.e",
5708 FT_BYTES, BASE_NONE, NULL, 0x0,
5709 NULL, HFILL }},
5711 { &hf_ssh_signature_length,
5712 { "Public key signature blob length", "ssh.pk_sig_blob_length",
5713 FT_UINT32, BASE_DEC, NULL, 0x0,
5714 NULL, HFILL }},
5716 { &hf_ssh_pk_sig_blob_name_length,
5717 { "Public key signature blob algorithm name length", "ssh.pk_sig_blob_name_length",
5718 FT_UINT32, BASE_DEC, NULL, 0x0,
5719 NULL, HFILL }},
5721 { &hf_ssh_pk_sig_blob_name,
5722 { "Public key signature blob algorithm name", "ssh.pk_sig_blob_name",
5723 FT_STRING, BASE_NONE, NULL, 0x0,
5724 NULL, HFILL }},
5726 { &hf_ssh_pk_sig_s_length,
5727 { "ssh-rsa signature length", "ssh.sig.ssh-rsa.length",
5728 FT_UINT32, BASE_DEC, NULL, 0x0,
5729 NULL, HFILL }},
5731 { &hf_ssh_pk_sig_s,
5732 { "ssh-rsa signature (s)", "ssh.sig.ssh-rsa.s",
5733 FT_BYTES, BASE_NONE, NULL, 0x0,
5734 NULL, HFILL }},
5736 { &hf_ssh_connection_type_name_len,
5737 { "Channel type name length", "ssh.connection_type_name_length",
5738 FT_UINT32, BASE_DEC, NULL, 0x0,
5739 NULL, HFILL }},
5741 { &hf_ssh_connection_type_name,
5742 { "Channel type name", "ssh.connection_type_name",
5743 FT_STRING, BASE_NONE, NULL, 0x0,
5744 NULL, HFILL }},
5746 { &hf_ssh_connection_sender_channel,
5747 { "Sender channel", "ssh.connection_sender_channel",
5748 FT_UINT32, BASE_DEC, NULL, 0x0,
5749 NULL, HFILL }},
5751 { &hf_ssh_connection_recipient_channel,
5752 { "Recipient channel", "ssh.connection_recipient_channel",
5753 FT_UINT32, BASE_DEC, NULL, 0x0,
5754 NULL, HFILL }},
5756 { &hf_ssh_connection_initial_window,
5757 { "Initial window size", "ssh.connection_initial_window_size",
5758 FT_UINT32, BASE_DEC, NULL, 0x0,
5759 NULL, HFILL }},
5761 { &hf_ssh_connection_maximum_packet_size,
5762 { "Maximum packet size", "ssh.userauth_maximum_packet_size",
5763 FT_UINT32, BASE_DEC, NULL, 0x0,
5764 NULL, HFILL }},
5766 { &hf_ssh_global_request_name_len,
5767 { "Global request name length", "ssh.global_request_name_length",
5768 FT_UINT32, BASE_DEC, NULL, 0x0,
5769 NULL, HFILL }},
5771 { &hf_ssh_global_request_name,
5772 { "Global request name", "ssh.global_request_name",
5773 FT_STRING, BASE_NONE, NULL, 0x0,
5774 NULL, HFILL }},
5776 { &hf_ssh_global_request_want_reply,
5777 { "Global request want reply", "ssh.global_request_want_reply",
5778 FT_UINT8, BASE_DEC, NULL, 0x0,
5779 NULL, HFILL }},
5781 { &hf_ssh_global_request_hostkeys_array_len,
5782 { "Host keys array length", "ssh.global_request_hostkeys",
5783 FT_UINT32, BASE_DEC, NULL, 0x0,
5784 NULL, HFILL }},
5786 { &hf_ssh_channel_request_name_len,
5787 { "Channel request name length", "ssh.channel_request_name_length",
5788 FT_UINT32, BASE_DEC, NULL, 0x0,
5789 NULL, HFILL }},
5791 { &hf_ssh_channel_request_name,
5792 { "Channel request name", "ssh.channel_request_name",
5793 FT_STRING, BASE_NONE, NULL, 0x0,
5794 NULL, HFILL }},
5796 { &hf_ssh_channel_request_want_reply,
5797 { "Channel request want reply", "ssh.channel_request_want_reply",
5798 FT_UINT8, BASE_DEC, NULL, 0x0,
5799 NULL, HFILL }},
5801 { &hf_ssh_subsystem_name_len,
5802 { "Subsystem name length", "ssh.subsystem_name_length",
5803 FT_UINT32, BASE_DEC, NULL, 0x0,
5804 NULL, HFILL }},
5806 { &hf_ssh_subsystem_name,
5807 { "Subsystem name", "ssh.subsystem_name",
5808 FT_STRING, BASE_NONE, NULL, 0x0,
5809 NULL, HFILL }},
5811 { &hf_ssh_exit_status,
5812 { "Exit status", "ssh.exit_status",
5813 FT_UINT32, BASE_HEX, NULL, 0x0,
5814 NULL, HFILL }},
5816 { &hf_ssh_channel_window_adjust,
5817 { "Bytes to add", "ssh.channel_window_adjust",
5818 FT_UINT32, BASE_DEC, NULL, 0x0,
5819 NULL, HFILL }},
5821 { &hf_ssh_channel_data_len,
5822 { "Data length", "ssh.channel_data_length",
5823 FT_UINT32, BASE_DEC, NULL, 0x0,
5824 NULL, HFILL }},
5826 { &hf_ssh_reassembled_in,
5827 { "Reassembled PDU in frame", "ssh.reassembled_in",
5828 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5829 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
5831 { &hf_ssh_reassembled_length,
5832 { "Reassembled PDU length", "ssh.reassembled.length",
5833 FT_UINT32, BASE_DEC, NULL, 0x0,
5834 "The total length of the reassembled payload", HFILL }},
5836 { &hf_ssh_reassembled_data,
5837 { "Reassembled PDU data", "ssh.reassembled.data",
5838 FT_BYTES, BASE_NONE, NULL, 0x00,
5839 "The payload of multiple reassembled SSH segments", HFILL }},
5841 { &hf_ssh_segments,
5842 { "Reassembled SSH segments", "ssh.segments",
5843 FT_NONE, BASE_NONE, NULL, 0x0,
5844 NULL, HFILL }},
5846 { &hf_ssh_segment,
5847 { "SSH segment", "ssh.segment",
5848 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5849 NULL, HFILL }},
5851 { &hf_ssh_segment_overlap,
5852 { "Segment overlap", "ssh.segment.overlap",
5853 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5854 "Segment overlaps with other segments", HFILL }},
5856 { &hf_ssh_segment_overlap_conflict,
5857 { "Conflicting data in segment overlap", "ssh.segment.overlap.conflict",
5858 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5859 "Overlapping segments contained conflicting data", HFILL }},
5861 { &hf_ssh_segment_multiple_tails,
5862 { "Multiple tail segments found", "ssh.segment.multipletails",
5863 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5864 "Several tails were found when reassembling the pdu", HFILL }},
5866 { &hf_ssh_segment_too_long_fragment,
5867 { "Segment too long", "ssh.segment.toolongfragment",
5868 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5869 "Segment contained data past end of the pdu", HFILL }},
5871 { &hf_ssh_segment_error,
5872 { "Reassembling error", "ssh.segment.error",
5873 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5874 "Reassembling error due to illegal segments", HFILL }},
5876 { &hf_ssh_segment_count,
5877 { "Segment count", "ssh.segment.count",
5878 FT_UINT32, BASE_DEC, NULL, 0x0,
5879 NULL, HFILL }},
5881 { &hf_ssh_segment_data,
5882 { "SSH segment data", "ssh.segment.data",
5883 FT_BYTES, BASE_NONE, NULL, 0x00,
5884 "The payload of a single SSH segment", HFILL }
5889 static int *ett[] = {
5890 &ett_ssh,
5891 &ett_key_exchange,
5892 &ett_key_exchange_host_key,
5893 &ett_key_exchange_host_sig,
5894 &ett_extension,
5895 &ett_userauth_pk_blob,
5896 &ett_userauth_pk_signautre,
5897 &ett_ssh1,
5898 &ett_ssh2,
5899 &ett_key_init,
5900 &ett_ssh_segments,
5901 &ett_ssh_segment
5904 static ei_register_info ei[] = {
5905 { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
5906 { &ei_ssh_packet_decode, { "ssh.packet_decode.error", PI_PROTOCOL, PI_WARN, "Packet decoded length not equal to packet length", EXPFILL }},
5907 { &ei_ssh_channel_number, { "ssh.channel_number.error", PI_PROTOCOL, PI_WARN, "Coud not find channel", EXPFILL }},
5908 { &ei_ssh_invalid_keylen, { "ssh.key_length.error", PI_PROTOCOL, PI_ERROR, "Invalid key length", EXPFILL }},
5909 { &ei_ssh_mac_bad, { "ssh.mac_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad MAC", EXPFILL }},
5912 module_t *ssh_module;
5913 expert_module_t *expert_ssh;
5915 proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
5916 proto_register_field_array(proto_ssh, hf, array_length(hf));
5917 proto_register_subtree_array(ett, array_length(ett));
5918 expert_ssh = expert_register_protocol(proto_ssh);
5919 expert_register_field_array(expert_ssh, ei, array_length(ei));
5921 #ifdef SSH_DECRYPT_DEBUG
5922 ssh_module = prefs_register_protocol(proto_ssh, ssh_prefs_apply_cb);
5923 #else
5924 ssh_module = prefs_register_protocol(proto_ssh, NULL);
5925 #endif
5926 prefs_register_bool_preference(ssh_module, "desegment_buffers",
5927 "Reassemble SSH buffers spanning multiple TCP segments",
5928 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
5929 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5930 &ssh_desegment);
5932 ssh_master_key_map = g_hash_table_new_full(ssh_hash, ssh_equal, ssh_free_glib_allocated_bignum, ssh_free_glib_allocated_entry);
5933 prefs_register_filename_preference(ssh_module, "keylog_file", "Key log filename",
5934 "The path to the file which contains a list of key exchange secrets in the following format:\n"
5935 "\"<hex-encoded-cookie> <PRIVATE_KEY|SHARED_SECRET> <hex-encoded-key>\" (without quotes or leading spaces).\n",
5936 &pref_keylog_file, false);
5938 prefs_register_filename_preference(ssh_module, "debug_file", "SSH debug file",
5939 "Redirect SSH debug to the file specified. Leave empty to disable debugging "
5940 "or use \"" SSH_DEBUG_USE_STDERR "\" to redirect output to stderr.",
5941 &ssh_debug_file_name, true);
5943 secrets_register_type(SECRETS_TYPE_SSH, ssh_secrets_block_callback);
5945 ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
5946 reassembly_table_register(&ssh_reassembly_table, &tcp_reassembly_table_functions);
5947 register_shutdown_routine(ssh_shutdown);
5950 void
5951 proto_reg_handoff_ssh(void)
5953 #ifdef SSH_DECRYPT_DEBUG
5954 ssh_set_debug(ssh_debug_file_name);
5955 #endif
5956 dissector_add_uint_range_with_preference("tcp.port", TCP_RANGE_SSH, ssh_handle);
5957 dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
5958 dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
5959 sftp_handle = find_dissector("sftp");
5963 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5965 * Local variables:
5966 * c-basic-offset: 4
5967 * tab-width: 8
5968 * indent-tabs-mode: nil
5969 * End:
5971 * vi: set shiftwidth=4 tabstop=8 expandtab:
5972 * :indentSize=4:tabSize=8:noTabs=true: