1 /* packet-ssh.c
2  * Routines for ssh packet dissection
3  *
4  * Huagang XIE <huagang@intruvert.com>
5  * Kees Cook <kees@outflux.net>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from packet-mysql.c
12  *
13  * SPDX-License-Identifier: GPL-2.0-or-later
14  *
15  *
16  * Note:  support SSH v1 and v2  now.
17  *
18  */
19 
20 /* SSH version 2 is defined in:
21  *
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
27  *
28  * SSH versions under 2 were never officially standardized.
29  *
30  * Diffie-Hellman Group Exchange is defined in:
31  *
32  * RFC 4419: Diffie-Hellman Group Exchange for
33  *   the Secure Shell (SSH) Transport Layer Protocol
34  */
35 
36 /* "SSH" prefixes are for version 2, whereas "SSH1" is for version 1 */
37 
38 #include "config.h"
39 
40 #include <errno.h>
41 
42 #include <epan/packet.h>
43 #include <epan/exceptions.h>
44 #include <epan/sctpppids.h>
45 #include <epan/prefs.h>
46 #include <epan/expert.h>
47 #include <wsutil/strtoi.h>
48 #include <wsutil/file_util.h>
49 #include <wsutil/filesystem.h>
50 #include <wsutil/wsgcrypt.h>
51 #include <wsutil/curve25519.h>
52 #include <wsutil/wslog.h>
53 
54 #include "packet-tcp.h"
55 
56 void proto_register_ssh(void);
57 void proto_reg_handoff_ssh(void);
58 
59 /* SSH Version 1 definition , from openssh ssh1.h */
60 #define SSH1_MSG_NONE           0   /* no message */
61 #define SSH1_MSG_DISCONNECT     1   /* cause (string) */
62 #define SSH1_SMSG_PUBLIC_KEY    2   /* ck,msk,srvk,hostk */
63 #define SSH1_CMSG_SESSION_KEY   3   /* key (BIGNUM) */
64 #define SSH1_CMSG_USER          4   /* user (string) */
65 
66 
67 #define SSH_VERSION_UNKNOWN     0
68 #define SSH_VERSION_1           1
69 #define SSH_VERSION_2           2
70 
71 /* proto data */
72 
73 #if GCRYPT_VERSION_NUMBER >= 0x010700 /* 1.7.0 */
74 #define SSH_DECRYPTION_SUPPORTED
75 #endif
76 
77 #ifdef SSH_DECRYPTION_SUPPORTED
78 typedef struct {
79     guint8  *data;
80     guint   length;
81 } ssh_kex_key;
82 
83 typedef struct {
84     guint8  *data;
85     guint   length;
86     guint8  type;
87 } ssh_kex_pub_key;
88 
89 typedef struct {
90     guint8  *data;
91     guint   length;
92 } ssh_enc_key;
93 
94 #define SSH_KEX_CURVE25519 1
95 #endif
96 
97 struct ssh_peer_data {
98     guint   counter;
99 
100     guint32 frame_version_start;
101     guint32 frame_version_end;
102 
103     guint32 frame_key_start;
104     guint32 frame_key_end;
105     int frame_key_end_offset;
106 
107     gchar*  kex_proposal;
108 
109     /* For all subsequent proposals,
110        [0] is client-to-server and [1] is server-to-client. */
111 #define CLIENT_TO_SERVER_PROPOSAL 0
112 #define SERVER_TO_CLIENT_PROPOSAL 1
113 
114     gchar*  mac_proposals[2];
115     gchar*  mac;
116     gint    mac_length;
117 
118     gchar*  enc_proposals[2];
119     gchar*  enc;
120 
121     gchar*  comp_proposals[2];
122     gchar*  comp;
123 
124     gint    length_is_plaintext;
125 };
126 
127 struct ssh_flow_data {
128     guint   version;
129 
130     gchar*  kex;
131     int   (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb,
132             packet_info *pinfo, int offset, proto_tree *tree,
133             struct ssh_flow_data *global_data);
134 
135     /* [0] is client's, [1] is server's */
136 #define CLIENT_PEER_DATA 0
137 #define SERVER_PEER_DATA 1
138     struct ssh_peer_data peer_data[2];
139 
140 #ifdef SSH_DECRYPTION_SUPPORTED
141     gchar           *session_id;
142     guint           session_id_length;
143     ssh_kex_pub_key     *kex_e;
144     wmem_array_t    *kex_hash_buffer;
145 #endif
146 };
147 
148 static int proto_ssh = -1;
149 
150 /* Version exchange */
151 static int hf_ssh_protocol = -1;
152 
153 /* Framing */
154 static int hf_ssh_packet_length = -1;
155 static int hf_ssh_packet_length_encrypted = -1;
156 static int hf_ssh_padding_length = -1;
157 static int hf_ssh_payload = -1;
158 static int hf_ssh_encrypted_packet = -1;
159 static int hf_ssh_padding_string = -1;
160 static int hf_ssh_mac_string = -1;
161 static int hf_ssh_direction = -1;
162 
163 /* Message codes */
164 static int hf_ssh_msg_code = -1;
165 static int hf_ssh2_msg_code = -1;
166 static int hf_ssh2_kex_dh_msg_code = -1;
167 static int hf_ssh2_kex_dh_gex_msg_code = -1;
168 static int hf_ssh2_kex_ecdh_msg_code = -1;
169 
170 /* Algorithm negotiation */
171 static int hf_ssh_cookie = -1;
172 static int hf_ssh_kex_algorithms = -1;
173 static int hf_ssh_server_host_key_algorithms = -1;
174 static int hf_ssh_encryption_algorithms_client_to_server = -1;
175 static int hf_ssh_encryption_algorithms_server_to_client = -1;
176 static int hf_ssh_mac_algorithms_client_to_server = -1;
177 static int hf_ssh_mac_algorithms_server_to_client = -1;
178 static int hf_ssh_compression_algorithms_client_to_server = -1;
179 static int hf_ssh_compression_algorithms_server_to_client = -1;
180 static int hf_ssh_languages_client_to_server = -1;
181 static int hf_ssh_languages_server_to_client = -1;
182 static int hf_ssh_kex_algorithms_length = -1;
183 static int hf_ssh_server_host_key_algorithms_length = -1;
184 static int hf_ssh_encryption_algorithms_client_to_server_length = -1;
185 static int hf_ssh_encryption_algorithms_server_to_client_length = -1;
186 static int hf_ssh_mac_algorithms_client_to_server_length = -1;
187 static int hf_ssh_mac_algorithms_server_to_client_length = -1;
188 static int hf_ssh_compression_algorithms_client_to_server_length = -1;
189 static int hf_ssh_compression_algorithms_server_to_client_length = -1;
190 static int hf_ssh_languages_client_to_server_length = -1;
191 static int hf_ssh_languages_server_to_client_length = -1;
192 static int hf_ssh_first_kex_packet_follows = -1;
193 static int hf_ssh_kex_reserved = -1;
194 static int hf_ssh_kex_hassh_algo = -1;
195 static int hf_ssh_kex_hassh = -1;
196 static int hf_ssh_kex_hasshserver_algo = -1;
197 static int hf_ssh_kex_hasshserver = -1;
198 
199 /* Key exchange common elements */
200 static int hf_ssh_hostkey_length = -1;
201 static int hf_ssh_hostkey_type_length = -1;
202 static int hf_ssh_hostkey_type = -1;
203 static int hf_ssh_hostkey_data = -1;
204 static int hf_ssh_hostkey_rsa_n = -1;
205 static int hf_ssh_hostkey_rsa_e = -1;
206 static int hf_ssh_hostkey_dsa_p = -1;
207 static int hf_ssh_hostkey_dsa_q = -1;
208 static int hf_ssh_hostkey_dsa_g = -1;
209 static int hf_ssh_hostkey_dsa_y = -1;
210 static int hf_ssh_hostkey_ecdsa_curve_id = -1;
211 static int hf_ssh_hostkey_ecdsa_curve_id_length = -1;
212 static int hf_ssh_hostkey_ecdsa_q = -1;
213 static int hf_ssh_hostkey_ecdsa_q_length = -1;
214 static int hf_ssh_hostkey_eddsa_key = -1;
215 static int hf_ssh_hostkey_eddsa_key_length = -1;
216 
217 static int hf_ssh_kex_h_sig = -1;
218 static int hf_ssh_kex_h_sig_length = -1;
219 
220 /* Key exchange: Diffie-Hellman */
221 static int hf_ssh_dh_e = -1;
222 static int hf_ssh_dh_f = -1;
223 
224 /* Key exchange: Diffie-Hellman Group Exchange */
225 static int hf_ssh_dh_gex_min = -1;
226 static int hf_ssh_dh_gex_nbits = -1;
227 static int hf_ssh_dh_gex_max = -1;
228 static int hf_ssh_dh_gex_p = -1;
229 static int hf_ssh_dh_gex_g = -1;
230 
231 /* Key exchange: Elliptic Curve Diffie-Hellman */
232 static int hf_ssh_ecdh_q_c = -1;
233 static int hf_ssh_ecdh_q_c_length = -1;
234 static int hf_ssh_ecdh_q_s = -1;
235 static int hf_ssh_ecdh_q_s_length = -1;
236 
237 /* Miscellaneous */
238 static int hf_ssh_mpint_length = -1;
239 
240 static gint ett_ssh = -1;
241 static gint ett_key_exchange = -1;
242 static gint ett_key_exchange_host_key = -1;
243 static gint ett_key_init = -1;
244 static gint ett_ssh1 = -1;
245 static gint ett_ssh2 = -1;
246 
247 static expert_field ei_ssh_packet_length = EI_INIT;
248 
249 static gboolean ssh_desegment = TRUE;
250 
251 static dissector_handle_t ssh_handle;
252 
253 #ifdef SSH_DECRYPTION_SUPPORTED
254 static const char   *pref_keylog_file;
255 static FILE         *ssh_keylog_file;
256 static wmem_map_t   *ssh_kex_keys;
257 #endif
258 
259 // 29418/tcp: Gerrit Code Review
260 #define TCP_RANGE_SSH  "22,29418"
261 #define SCTP_PORT_SSH 22
262 
263 /* Message Numbers (from RFC 4250) (1-255) */
264 
265 /* Transport layer protocol: generic (1-19) */
266 #define SSH_MSG_DISCONNECT          1
267 #define SSH_MSG_IGNORE              2
268 #define SSH_MSG_UNIMPLEMENTED       3
269 #define SSH_MSG_DEBUG               4
270 #define SSH_MSG_SERVICE_REQUEST     5
271 #define SSH_MSG_SERVICE_ACCEPT      6
272 
273 /* Transport layer protocol: Algorithm negotiation (20-29) */
274 #define SSH_MSG_KEXINIT             20
275 #define SSH_MSG_NEWKEYS             21
276 
277 /* Transport layer: Key exchange method specific (reusable) (30-49) */
278 #define SSH_MSG_KEXDH_INIT          30
279 #define SSH_MSG_KEXDH_REPLY         31
280 
281 #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD  30
282 #define SSH_MSG_KEX_DH_GEX_GROUP        31
283 #define SSH_MSG_KEX_DH_GEX_INIT         32
284 #define SSH_MSG_KEX_DH_GEX_REPLY        33
285 #define SSH_MSG_KEX_DH_GEX_REQUEST      34
286 
287 #define SSH_MSG_KEX_ECDH_INIT       30
288 #define SSH_MSG_KEX_ECDH_REPLY      31
289 
290 /* User authentication protocol: generic (50-59) */
291 #define SSH_MSG_USERAUTH_REQUEST    50
292 #define SSH_MSG_USERAUTH_FAILURE    51
293 #define SSH_MSG_USERAUTH_SUCCESS    52
294 #define SSH_MSG_USERAUTH_BANNER     53
295 
296 /* User authentication protocol: method specific (reusable) (50-79) */
297 
298 /* Connection protocol: generic (80-89) */
299 #define SSH_MSG_GLOBAL_REQUEST          80
300 #define SSH_MSG_REQUEST_SUCCESS         81
301 #define SSH_MSG_REQUEST_FAILURE         82
302 
303 /* Connection protocol: channel related messages (90-127) */
304 #define SSH_MSG_CHANNEL_OPEN                90
305 #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION   91
306 #define SSH_MSG_CHANNEL_OPEN_FAILURE        92
307 #define SSH_MSG_CHANNEL_WINDOW_ADJUST       93
308 #define SSH_MSG_CHANNEL_DATA                94
309 #define SSH_MSG_CHANNEL_EXTENDED_DATA       95
310 #define SSH_MSG_CHANNEL_EOF                 96
311 #define SSH_MSG_CHANNEL_CLOSE               97
312 #define SSH_MSG_CHANNEL_REQUEST             98
313 #define SSH_MSG_CHANNEL_SUCCESS             99
314 #define SSH_MSG_CHANNEL_FAILURE             100
315 
316 /* 128-191 reserved for client protocols */
317 /* 192-255 local extensions */
318 
319 static const value_string ssh_direction_vals[] = {
320     { CLIENT_TO_SERVER_PROPOSAL, "client-to-server" },
321     { SERVER_TO_CLIENT_PROPOSAL, "server-to-client" },
322     { 0, NULL }
323 };
324 
325 static const value_string ssh2_msg_vals[] = {
326     { SSH_MSG_DISCONNECT,                "Disconnect" },
327     { SSH_MSG_IGNORE,                    "Ignore" },
328     { SSH_MSG_UNIMPLEMENTED,             "Unimplemented" },
329     { SSH_MSG_DEBUG,                     "Debug" },
330     { SSH_MSG_SERVICE_REQUEST,           "Service Request" },
331     { SSH_MSG_SERVICE_ACCEPT,            "Service Accept" },
332     { SSH_MSG_KEXINIT,                   "Key Exchange Init" },
333     { SSH_MSG_NEWKEYS,                   "New Keys" },
334     { SSH_MSG_USERAUTH_REQUEST,          "User Authentication Request" },
335     { SSH_MSG_USERAUTH_FAILURE,          "User Authentication Failure" },
336     { SSH_MSG_USERAUTH_SUCCESS,          "User Authentication Success" },
337     { SSH_MSG_USERAUTH_BANNER,           "User Authentication Banner" },
338     { SSH_MSG_GLOBAL_REQUEST,            "Global Request" },
339     { SSH_MSG_REQUEST_SUCCESS,           "Request Success" },
340     { SSH_MSG_REQUEST_FAILURE,           "Request Failure" },
341     { SSH_MSG_CHANNEL_OPEN,              "Channel Open" },
342     { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
343     { SSH_MSG_CHANNEL_OPEN_FAILURE,      "Channel Open Failure" },
344     { SSH_MSG_CHANNEL_WINDOW_ADJUST,     "Window Adjust" },
345     { SSH_MSG_CHANNEL_DATA,              "Channel Data" },
346     { SSH_MSG_CHANNEL_EXTENDED_DATA,     "Channel Extended Data" },
347     { SSH_MSG_CHANNEL_EOF,               "Channel EOF" },
348     { SSH_MSG_CHANNEL_CLOSE,             "Channel Close" },
349     { SSH_MSG_CHANNEL_REQUEST,           "Channel Request" },
350     { SSH_MSG_CHANNEL_SUCCESS,           "Channel Success" },
351     { SSH_MSG_CHANNEL_FAILURE,           "Channel Failure" },
352     { 0, NULL }
353 };
354 
355 static const value_string ssh2_kex_dh_msg_vals[] = {
356     { SSH_MSG_KEXDH_INIT,                "Diffie-Hellman Key Exchange Init" },
357     { SSH_MSG_KEXDH_REPLY,               "Diffie-Hellman Key Exchange Reply" },
358     { 0, NULL }
359 };
360 
361 static const value_string ssh2_kex_dh_gex_msg_vals[] = {
362     { SSH_MSG_KEX_DH_GEX_REQUEST_OLD,    "Diffie-Hellman Group Exchange Request (Old)" },
363     { SSH_MSG_KEX_DH_GEX_GROUP,          "Diffie-Hellman Group Exchange Group" },
364     { SSH_MSG_KEX_DH_GEX_INIT,           "Diffie-Hellman Group Exchange Init" },
365     { SSH_MSG_KEX_DH_GEX_REPLY,          "Diffie-Hellman Group Exchange Reply" },
366     { SSH_MSG_KEX_DH_GEX_REQUEST,        "Diffie-Hellman Group Exchange Request" },
367     { 0, NULL }
368 };
369 
370 static const value_string ssh2_kex_ecdh_msg_vals[] = {
371     { SSH_MSG_KEX_ECDH_INIT,             "Elliptic Curve Diffie-Hellman Key Exchange Init" },
372     { SSH_MSG_KEX_ECDH_REPLY,            "Elliptic Curve Diffie-Hellman Key Exchange Reply" },
373     { 0, NULL }
374 };
375 
376 static const value_string ssh1_msg_vals[] = {
377     {SSH1_MSG_NONE,                      "No Message"},
378     {SSH1_MSG_DISCONNECT,                "Disconnect"},
379     {SSH1_SMSG_PUBLIC_KEY,               "Public Key"},
380     {SSH1_CMSG_SESSION_KEY,              "Session Key"},
381     {SSH1_CMSG_USER,                     "User"},
382     {0, NULL}
383 };
384 
385 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
386         int is_response,
387         struct ssh_flow_data *global_data);
388 static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
389         int hf_index_length, int hf_index_value, char **store);
390 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
391         struct ssh_flow_data *global_data,
392         int offset, proto_tree *tree, int is_response,
393         gboolean *need_desegmentation);
394 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
395         struct ssh_flow_data *global_data,
396         int offset, proto_tree *tree, int is_response,
397         gboolean *need_desegmentation);
398 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
399         struct ssh_flow_data *global_data,
400         int offset, proto_tree *tree, int is_response,
401         gboolean *need_desegmentation);
402 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
403         packet_info *pinfo, int offset, proto_tree *tree,
404         struct ssh_flow_data *global_data);
405 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
406         packet_info *pinfo, int offset, proto_tree *tree,
407         struct ssh_flow_data *global_data);
408 static int ssh_dissect_kex_ecdh(guint8 msg_code, tvbuff_t *tvb,
409         packet_info *pinfo, int offset, proto_tree *tree,
410         struct ssh_flow_data *global_data);
411 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
412         struct ssh_flow_data *global_data,
413         int offset, proto_tree *tree, int is_response, guint *version,
414         gboolean *need_desegmentation);
415 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
416         struct ssh_peer_data *peer_data,
417         int offset, proto_tree *tree);
418 static void ssh_choose_algo(gchar *client, gchar *server, gchar **result);
419 static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
420 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
421 
422 #ifdef SSH_DECRYPTION_SUPPORTED
423 static void ssh_keylog_read_file(void);
424 static void ssh_keylog_process_line(char *line);
425 static void ssh_keylog_reset(void);
426 static void ssh_keylog_add_keys(guint8 *priv, guint priv_length,
427         gchar *type_string);
428 static ssh_kex_key *ssh_kex_make_key(guint8 *data, guint length);
429 static ssh_kex_pub_key *ssh_kex_make_pub_key(guint8 *data, guint length,
430         gchar type);
431 static void ssh_read_e(tvbuff_t *tvb, int offset,
432         struct ssh_flow_data *global_data);
433 static void ssh_keylog_compute_hash(tvbuff_t *tvb, int offset,
434         struct ssh_flow_data *global_data);
435 static ssh_kex_key *ssh_kex_shared_secret(ssh_kex_pub_key *pub, ssh_kex_key *priv);
436 static void ssh_hash_buffer_put_string(wmem_array_t *buffer, const gchar *string,
437         guint len);
438 static gchar *ssh_string(const gchar *string, guint len);
439 static void ssh_derive_symmetric_keys(ssh_kex_key *shared_secret,
440         gchar *exchange_hash, guint hash_length,
441         struct ssh_flow_data *global_data);
442 static void ssh_derive_symmetric_key(ssh_kex_key *shared_secret,
443         gchar *exchange_hash, guint hash_length, gchar id,
444         ssh_enc_key *result_key, struct ssh_flow_data *global_data);
445 #endif
446 
447 static int
dissect_ssh(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)448 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
449 {
450     proto_tree  *ssh_tree;
451     proto_item  *ti;
452     conversation_t *conversation;
453     int         last_offset, offset = 0;
454 
455     gboolean    is_response = (pinfo->destport != pinfo->match_uint),
456                 need_desegmentation;
457     guint       version;
458 
459     struct ssh_flow_data *global_data = NULL;
460     struct ssh_peer_data *peer_data;
461 
462     conversation = find_or_create_conversation(pinfo);
463 
464     global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
465     if (!global_data) {
466         global_data = wmem_new0(wmem_file_scope(), struct ssh_flow_data);
467         global_data->version = SSH_VERSION_UNKNOWN;
468         global_data->kex_specific_dissector = ssh_dissect_kex_dh;
469         global_data->peer_data[CLIENT_PEER_DATA].mac_length = -1;
470         global_data->peer_data[SERVER_PEER_DATA].mac_length = -1;
471 #ifdef SSH_DECRYPTION_SUPPORTED
472         global_data->kex_hash_buffer = wmem_array_new(wmem_file_scope(), 1);
473 #endif
474 
475         conversation_add_proto_data(conversation, proto_ssh, global_data);
476     }
477 
478     peer_data = &global_data->peer_data[is_response];
479 
480     ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
481     ssh_tree = proto_item_add_subtree(ti, ett_ssh);
482 
483     version = global_data->version;
484 
485     switch(version) {
486     case SSH_VERSION_UNKNOWN:
487         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
488         break;
489     case SSH_VERSION_1:
490         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
491         break;
492     case SSH_VERSION_2:
493         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
494         break;
495 
496     }
497 
498     col_clear(pinfo->cinfo, COL_INFO);
499 
500     while(tvb_reported_length_remaining(tvb, offset)> 0) {
501         gboolean after_version_start = (peer_data->frame_version_start == 0 ||
502             pinfo->num >= peer_data->frame_version_start);
503         gboolean before_version_end = (peer_data->frame_version_end == 0 ||
504             pinfo->num <= peer_data->frame_version_end);
505 
506         need_desegmentation = FALSE;
507         last_offset = offset;
508 
509         peer_data->counter++;
510 
511         if (after_version_start && before_version_end &&
512               (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
513             if (peer_data->frame_version_start == 0)
514                 peer_data->frame_version_start = pinfo->num;
515 
516             offset = ssh_dissect_protocol(tvb, pinfo,
517                     global_data,
518                     offset, ssh_tree, is_response,
519                     &version, &need_desegmentation);
520 
521             if (!need_desegmentation) {
522                 peer_data->frame_version_end = pinfo->num;
523                 global_data->version = version;
524             }
525         } else {
526             switch(version) {
527 
528             case SSH_VERSION_UNKNOWN:
529                 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
530                         &global_data->peer_data[is_response], offset, ssh_tree);
531                 break;
532 
533             case SSH_VERSION_1:
534                 offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
535                         offset, ssh_tree, is_response,
536                         &need_desegmentation);
537                 break;
538 
539             case SSH_VERSION_2:
540                 offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
541                         offset, ssh_tree, is_response,
542                         &need_desegmentation);
543                 break;
544             }
545         }
546 
547         if (need_desegmentation)
548             return tvb_captured_length(tvb);
549         if (offset <= last_offset) {
550             /* XXX - add an expert info in the function
551                that decrements offset */
552             break;
553         }
554     }
555 
556     col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
557     ti = proto_tree_add_boolean_format_value(ssh_tree, hf_ssh_direction, tvb, 0, 0, is_response, "%s",
558         try_val_to_str(is_response, ssh_direction_vals));
559     proto_item_set_generated(ti);
560     return tvb_captured_length(tvb);
561 }
562 
563 static int
ssh_dissect_ssh2(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,gboolean * need_desegmentation)564 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
565         struct ssh_flow_data *global_data,
566         int offset, proto_tree *tree, int is_response,
567         gboolean *need_desegmentation)
568 {
569     proto_item *ssh2_tree = NULL;
570     int last_offset = offset;
571 
572     struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
573 
574     if (tree) {
575         wmem_strbuf_t *title = wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2");
576 
577         if (peer_data->enc || peer_data->mac || peer_data->comp) {
578             wmem_strbuf_append_printf(title, " (");
579             if (peer_data->enc)
580                 wmem_strbuf_append_printf(title, "encryption:%s%s",
581                     peer_data->enc,
582                     peer_data->mac || peer_data->comp
583                         ? " " : "");
584             if (peer_data->mac)
585                 wmem_strbuf_append_printf(title, "mac:%s%s",
586                     peer_data->mac,
587                     peer_data->comp ? " " : "");
588             if (peer_data->comp)
589                 wmem_strbuf_append_printf(title, "compression:%s",
590                     peer_data->comp);
591             wmem_strbuf_append_printf(title, ")");
592         }
593 
594         ssh2_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title));
595     }
596 
597     if ((peer_data->frame_key_start == 0) ||
598         ((peer_data->frame_key_start <= pinfo->num) &&
599         ((peer_data->frame_key_end == 0) || (pinfo->num < peer_data->frame_key_end) ||
600                 ((pinfo->num == peer_data->frame_key_end) && (offset < peer_data->frame_key_end_offset))))) {
601         offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
602             offset, ssh2_tree, is_response,
603             need_desegmentation);
604     } else {
605         offset = ssh_dissect_encrypted_packet(tvb, pinfo,
606                 &global_data->peer_data[is_response], offset, ssh2_tree);
607     }
608 
609     if (ssh2_tree) {
610         proto_item_set_len(ssh2_tree, offset - last_offset);
611     }
612 
613     return offset;
614 }
615 static int
ssh_dissect_ssh1(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,gboolean * need_desegmentation)616 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
617         struct ssh_flow_data *global_data,
618         int offset, proto_tree *tree, int is_response,
619         gboolean *need_desegmentation)
620 {
621     guint   plen, padding_length, len;
622     guint8  msg_code;
623     guint   remain_length;
624 
625     proto_item *ssh1_tree;
626 
627     struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
628 
629     ssh1_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1");
630 
631     /*
632      * We use "tvb_ensure_captured_length_remaining()" to make sure there
633      * actually *is* data remaining.
634      *
635      * This means we're guaranteed that "remain_length" is positive.
636      */
637     remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
638     /*
639      * Can we do reassembly?
640      */
641     if (ssh_desegment && pinfo->can_desegment) {
642         /*
643          * Yes - would an SSH header starting at this offset be split
644          * across segment boundaries?
645          */
646         if (remain_length < 4) {
647             /*
648              * Yes.  Tell the TCP dissector where the data for
649              * this message starts in the data it handed us and
650              * that we need "some more data."  Don't tell it
651              * exactly how many bytes we need because if/when we
652              * ask for even more (after the header) that will
653              * break reassembly.
654              */
655             pinfo->desegment_offset = offset;
656             pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
657             *need_desegmentation = TRUE;
658             return offset;
659         }
660     }
661     plen = tvb_get_ntohl(tvb, offset) ;
662     padding_length  = 8 - plen%8;
663 
664 
665     if (ssh_desegment && pinfo->can_desegment) {
666         if (plen+4+padding_length >  remain_length) {
667             pinfo->desegment_offset = offset;
668             pinfo->desegment_len = plen+padding_length - remain_length;
669             *need_desegmentation = TRUE;
670             return offset;
671         }
672     }
673 
674     if (plen >= 0xffff) {
675         if (ssh1_tree && plen > 0) {
676               proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
677                 offset, 4, plen, "Overly large length %x", plen);
678         }
679         plen = remain_length-4-padding_length;
680     } else {
681         if (ssh1_tree && plen > 0) {
682               proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
683                 offset, 4, plen);
684         }
685     }
686     offset+=4;
687     /* padding length */
688 
689     proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
690             offset, padding_length, padding_length);
691     offset += padding_length;
692 
693     /* msg_code */
694     if ((peer_data->frame_key_start == 0) ||
695         ((peer_data->frame_key_start >= pinfo->num) && (pinfo->num <= peer_data->frame_key_end))) {
696         msg_code = tvb_get_guint8(tvb, offset);
697 
698         proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
699         col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
700             val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
701         offset += 1;
702         len = plen -1;
703         if (!pinfo->fd->visited) {
704             if (peer_data->frame_key_start == 0)
705                 peer_data->frame_key_start = pinfo->num;
706             peer_data->frame_key_end = pinfo->num;
707         }
708     } else {
709         len = plen;
710         col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
711     }
712     /* payload */
713     if (ssh1_tree) {
714         proto_tree_add_item(ssh1_tree, hf_ssh_payload,
715             tvb, offset, len, ENC_NA);
716     }
717     offset += len;
718 
719     return offset;
720 }
721 
722 static int
ssh_tree_add_mpint(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_ssh_mpint_selection)723 ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
724     int hf_ssh_mpint_selection)
725 {
726     guint len = tvb_get_ntohl(tvb, offset);
727     proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
728             offset, 4, len);
729     offset+=4;
730     proto_tree_add_item(tree, hf_ssh_mpint_selection,
731             tvb, offset, len, ENC_NA);
732     return 4+len;
733 }
734 
735 static int
ssh_tree_add_string(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_ssh_string,int hf_ssh_string_length)736 ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
737     int hf_ssh_string, int hf_ssh_string_length)
738 {
739     guint len = tvb_get_ntohl(tvb, offset);
740     proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
741             offset, 4, len);
742     offset+=4;
743     proto_tree_add_item(tree, hf_ssh_string,
744             tvb, offset, len, ENC_NA);
745     return 4+len;
746 }
747 
748 static guint
ssh_tree_add_hostkey(tvbuff_t * tvb,int offset,proto_tree * parent_tree,const char * tree_name,int ett_idx,struct ssh_flow_data * global_data)749 ssh_tree_add_hostkey(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
750                      const char *tree_name, int ett_idx,
751                      struct ssh_flow_data *global_data)
752 {
753     proto_tree *tree = NULL;
754     int last_offset;
755     int remaining_len;
756     guint key_len, type_len;
757     char* key_type;
758     gchar *tree_title;
759 
760     last_offset = offset;
761 
762     key_len = tvb_get_ntohl(tvb, offset);
763     offset += 4;
764 
765     /* Read the key type before creating the tree so we can append it as info. */
766     type_len = tvb_get_ntohl(tvb, offset);
767     offset += 4;
768     key_type = (char *) tvb_get_string_enc(wmem_packet_scope(), tvb, offset, type_len, ENC_ASCII|ENC_NA);
769 
770     tree_title = wmem_strdup_printf(wmem_packet_scope(), "%s (type: %s)", tree_name, key_type);
771     tree = proto_tree_add_subtree(parent_tree, tvb, last_offset, key_len + 4, ett_idx, NULL,
772                                   tree_title);
773 
774     proto_tree_add_uint(tree, hf_ssh_hostkey_length, tvb, last_offset, 4, key_len);
775 
776     // server host key (K_S / Q)
777 #ifdef SSH_DECRYPTION_SUPPORTED
778     gchar *data = (gchar *)tvb_memdup(wmem_packet_scope(), tvb, last_offset + 4, key_len);
779     ssh_hash_buffer_put_string(global_data->kex_hash_buffer, data, key_len);
780 #else
781     // ignore unused parameter complaint
782     (void)global_data;
783 #endif
784 
785     last_offset += 4;
786     proto_tree_add_uint(tree, hf_ssh_hostkey_type_length, tvb, last_offset, 4, type_len);
787     proto_tree_add_string(tree, hf_ssh_hostkey_type, tvb, offset, type_len, key_type);
788     offset += type_len;
789 
790     if (0 == strcmp(key_type, "ssh-rsa")) {
791         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_e);
792         ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_n);
793     } else if (0 == strcmp(key_type, "ssh-dss")) {
794         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_p);
795         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_q);
796         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_g);
797         ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_y);
798     } else if (g_str_has_prefix(key_type, "ecdsa-sha2-")) {
799         offset += ssh_tree_add_string(tvb, offset, tree,
800                                       hf_ssh_hostkey_ecdsa_curve_id, hf_ssh_hostkey_ecdsa_curve_id_length);
801         ssh_tree_add_string(tvb, offset, tree,
802                             hf_ssh_hostkey_ecdsa_q, hf_ssh_hostkey_ecdsa_q_length);
803     } else if (g_str_has_prefix(key_type, "ssh-ed")) {
804         ssh_tree_add_string(tvb, offset, tree,
805                             hf_ssh_hostkey_eddsa_key, hf_ssh_hostkey_eddsa_key_length);
806     } else {
807         remaining_len = key_len - (type_len + 4);
808         proto_tree_add_item(tree, hf_ssh_hostkey_data, tvb, offset, remaining_len, ENC_NA);
809     }
810 
811     return 4+key_len;
812 }
813 
814 static int
ssh_dissect_key_exchange(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,gboolean * need_desegmentation)815 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
816         struct ssh_flow_data *global_data,
817         int offset, proto_tree *tree, int is_response,
818         gboolean *need_desegmentation)
819 {
820     guint   plen, len;
821     guint8  padding_length;
822     guint   remain_length;
823     int     last_offset = offset;
824     guint   msg_code;
825 
826     proto_item *ti;
827     proto_item *key_ex_tree = NULL;
828     const gchar *key_ex_title = "Key Exchange";
829 
830     struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
831 
832     /*
833      * We use "tvb_ensure_captured_length_remaining()" to make sure there
834      * actually *is* data remaining.
835      *
836      * This means we're guaranteed that "remain_length" is positive.
837      */
838     remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
839     /*
840      * Can we do reassembly?
841      */
842     if (ssh_desegment && pinfo->can_desegment) {
843         /*
844          * Yes - would an SSH header starting at this offset
845          * be split across segment boundaries?
846          */
847         if (remain_length < 4) {
848             /*
849              * Yes.  Tell the TCP dissector where the data for
850              * this message starts in the data it handed us and
851              * that we need "some more data."  Don't tell it
852              * exactly how many bytes we need because if/when we
853              * ask for even more (after the header) that will
854              * break reassembly.
855              */
856             pinfo->desegment_offset = offset;
857             pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
858             *need_desegmentation = TRUE;
859             return offset;
860         }
861     }
862     plen = tvb_get_ntohl(tvb, offset) ;
863 
864     if (ssh_desegment && pinfo->can_desegment) {
865         if (plen +4 >  remain_length) {
866             pinfo->desegment_offset = offset;
867             pinfo->desegment_len = plen+4 - remain_length;
868             *need_desegmentation = TRUE;
869             return offset;
870         }
871     }
872     /*
873      * Need to check plen > 0x80000000 here
874      */
875 
876     ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
877                     offset, 4, plen);
878     if (plen >= 0xffff) {
879         expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
880         plen = remain_length-4;
881     }
882     offset+=4;
883 
884     /* padding length */
885     padding_length = tvb_get_guint8(tvb, offset);
886     proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
887     offset += 1;
888 
889     if (global_data->kex)
890         key_ex_title = wmem_strdup_printf(wmem_packet_scope(), "%s (method:%s)", key_ex_title, global_data->kex);
891     key_ex_tree = proto_tree_add_subtree(tree, tvb, offset, plen-1, ett_key_exchange, NULL, key_ex_title);
892 
893     /* msg_code */
894     msg_code = tvb_get_guint8(tvb, offset);
895 
896     if (msg_code >= 30 && msg_code < 40) {
897         offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo,
898                 offset, key_ex_tree, global_data);
899     } else {
900         proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
901         offset += 1;
902 
903         col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
904             val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
905 
906         /* 16 bytes cookie  */
907         switch(msg_code)
908         {
909         case SSH_MSG_KEXINIT:
910             if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->num)) {
911                 offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
912                 peer_data->frame_key_start = pinfo->num;
913             }
914             break;
915         case SSH_MSG_NEWKEYS:
916             if (peer_data->frame_key_end == 0) {
917                 peer_data->frame_key_end = pinfo->num;
918                 peer_data->frame_key_end_offset = offset;
919                 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response],
920                                 global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response],
921                                 &peer_data->enc);
922 
923                 /* some ciphers have their own MAC so the "negotiated" one is meaningless */
924                 if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
925                                       0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
926                     peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
927                     peer_data->mac_length = 16;
928                     peer_data->length_is_plaintext = 1;
929                 }
930                 else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
931                     peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
932                     peer_data->mac_length = 16;
933                 }
934                 else {
935                     ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response],
936                                     global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response],
937                                     &peer_data->mac);
938                     ssh_set_mac_length(peer_data);
939                 }
940 
941                 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response],
942                                 global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response],
943                                 &peer_data->comp);
944             }
945             break;
946         }
947     }
948 
949     len = plen+4-padding_length-(offset-last_offset);
950     if (len > 0) {
951         proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
952     }
953     offset += len;
954 
955     /* padding */
956     proto_tree_add_item(tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
957     offset+= padding_length;
958 
959     return offset;
960 }
961 
ssh_dissect_kex_dh(guint8 msg_code,tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,struct ssh_flow_data * global_data)962 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
963         packet_info *pinfo, int offset, proto_tree *tree,
964         struct ssh_flow_data *global_data)
965 {
966     proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
967     offset += 1;
968 
969     col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
970         val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
971 
972     switch (msg_code) {
973     case SSH_MSG_KEXDH_INIT:
974 #ifdef SSH_DECRYPTION_SUPPORTED
975         // e (client ephemeral key public part)
976         ssh_read_e(tvb, offset, global_data);
977 #endif
978 
979         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
980         break;
981 
982     case SSH_MSG_KEXDH_REPLY:
983         offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
984                 ett_key_exchange_host_key, global_data);
985 
986 #ifdef SSH_DECRYPTION_SUPPORTED
987         // f (server ephemeral key public part), K_S (host key)
988         ssh_keylog_compute_hash(tvb, offset, global_data);
989 #endif
990 
991         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
992         offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kex_h_sig, hf_ssh_kex_h_sig_length);
993         break;
994     }
995 
996     return offset;
997 }
998 
ssh_dissect_kex_dh_gex(guint8 msg_code,tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,struct ssh_flow_data * global_data)999 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
1000         packet_info *pinfo, int offset, proto_tree *tree,
1001         struct ssh_flow_data *global_data)
1002 {
1003     proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1004     offset += 1;
1005 
1006     col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1007         val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
1008 
1009     switch (msg_code) {
1010     case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
1011         proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1012         offset += 4;
1013         break;
1014 
1015     case SSH_MSG_KEX_DH_GEX_GROUP:
1016         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_p);
1017         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_g);
1018         break;
1019 
1020     case SSH_MSG_KEX_DH_GEX_INIT:
1021         // TODO allow decryption with this key exchange method
1022         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
1023         break;
1024 
1025     case SSH_MSG_KEX_DH_GEX_REPLY:
1026         offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1027                 ett_key_exchange_host_key, global_data);
1028         offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
1029         offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kex_h_sig, hf_ssh_kex_h_sig_length);
1030         break;
1031 
1032     case SSH_MSG_KEX_DH_GEX_REQUEST:
1033         proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
1034         offset += 4;
1035         proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1036         offset += 4;
1037         proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
1038         offset += 4;
1039         break;
1040     }
1041 
1042     return offset;
1043 }
1044 
1045 static int
ssh_dissect_kex_ecdh(guint8 msg_code,tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,struct ssh_flow_data * global_data)1046 ssh_dissect_kex_ecdh(guint8 msg_code, tvbuff_t *tvb,
1047         packet_info *pinfo, int offset, proto_tree *tree,
1048         struct ssh_flow_data *global_data)
1049 {
1050     proto_tree_add_item(tree, hf_ssh2_kex_ecdh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1051     offset += 1;
1052 
1053     col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1054         val_to_str(msg_code, ssh2_kex_ecdh_msg_vals, "Unknown (%u)"));
1055 
1056     switch (msg_code) {
1057     case SSH_MSG_KEX_ECDH_INIT:
1058 #ifdef SSH_DECRYPTION_SUPPORTED
1059         ssh_read_e(tvb, offset, global_data);
1060 #endif
1061 
1062         offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_c, hf_ssh_ecdh_q_c_length);
1063         break;
1064 
1065     case SSH_MSG_KEX_ECDH_REPLY:
1066         offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1067                 ett_key_exchange_host_key, global_data);
1068 
1069 #ifdef SSH_DECRYPTION_SUPPORTED
1070         ssh_keylog_compute_hash(tvb, offset, global_data);
1071 #endif
1072 
1073         offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_s, hf_ssh_ecdh_q_s_length);
1074         offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kex_h_sig, hf_ssh_kex_h_sig_length);
1075         break;
1076     }
1077 
1078     return offset;
1079 }
1080 
1081 static int
ssh_dissect_encrypted_packet(tvbuff_t * tvb,packet_info * pinfo,struct ssh_peer_data * peer_data,int offset,proto_tree * tree)1082 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
1083         struct ssh_peer_data *peer_data,
1084         int offset, proto_tree *tree)
1085 {
1086     gint len;
1087     guint plen;
1088 
1089     len = tvb_reported_length_remaining(tvb, offset);
1090     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
1091 
1092     if (tree) {
1093         gint encrypted_len = len;
1094 
1095         if (len > 4 && peer_data->length_is_plaintext) {
1096             plen = tvb_get_ntohl(tvb, offset) ;
1097             proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
1098             encrypted_len -= 4;
1099         }
1100         else if (len > 4) {
1101             proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
1102             encrypted_len -= 4;
1103         }
1104 
1105         if (peer_data->mac_length>0)
1106             encrypted_len -= peer_data->mac_length;
1107 
1108         proto_tree_add_item(tree, hf_ssh_encrypted_packet,
1109                     tvb, offset+4, encrypted_len, ENC_NA);
1110 
1111         if (peer_data->mac_length>0)
1112             proto_tree_add_item(tree, hf_ssh_mac_string,
1113                 tvb, offset+4+encrypted_len,
1114                 peer_data->mac_length, ENC_NA);
1115     }
1116     offset += len;
1117     return offset;
1118 }
1119 
1120 static int
ssh_dissect_protocol(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,guint * version,gboolean * need_desegmentation)1121 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
1122         struct ssh_flow_data *global_data,
1123         int offset, proto_tree *tree, int is_response, guint * version,
1124         gboolean *need_desegmentation)
1125 {
1126     guint   remain_length;
1127     gint    linelen, protolen;
1128 
1129     /*
1130      *  If the first packet do not contain the banner,
1131      *  it is dump in the middle of a flow or not a ssh at all
1132      */
1133     if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
1134         offset = ssh_dissect_encrypted_packet(tvb, pinfo,
1135             &global_data->peer_data[is_response], offset, tree);
1136         return offset;
1137     }
1138 
1139     if (!is_response) {
1140         if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
1141             *(version) = SSH_VERSION_2;
1142         } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
1143             *(version) = SSH_VERSION_2;
1144         } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
1145             *(version) = SSH_VERSION_1;
1146         }
1147     }
1148 
1149     /*
1150      * We use "tvb_ensure_captured_length_remaining()" to make sure there
1151      * actually *is* data remaining.
1152      *
1153      * This means we're guaranteed that "remain_length" is positive.
1154      */
1155     remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1156     /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1157      */
1158     linelen = tvb_find_guint8(tvb, offset, -1, '\n');
1159 
1160     if (ssh_desegment && pinfo->can_desegment) {
1161         if (linelen == -1 || remain_length < (guint)linelen-offset) {
1162             pinfo->desegment_offset = offset;
1163             pinfo->desegment_len = linelen-remain_length;
1164             *need_desegmentation = TRUE;
1165             return offset;
1166         }
1167     }
1168     if (linelen == -1) {
1169         /* XXX - reassemble across segment boundaries? */
1170         linelen = remain_length;
1171         protolen = linelen;
1172     } else {
1173         linelen = linelen - offset + 1;
1174 
1175         if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r')
1176             protolen = linelen - 2;
1177         else
1178             protolen = linelen - 1;
1179     }
1180 
1181     col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
1182             tvb_format_text(pinfo->pool, tvb, offset, protolen));
1183 
1184     // V_C / V_S (client and server identification strings) RFC4253 4.2
1185     // format: SSH-protoversion-softwareversion SP comments [CR LF not incl.]
1186 #ifdef SSH_DECRYPTION_SUPPORTED
1187     gchar *data = (gchar *)tvb_memdup(wmem_packet_scope(), tvb, offset, protolen);
1188     ssh_hash_buffer_put_string(global_data->kex_hash_buffer, data, protolen);
1189 #endif
1190 
1191     proto_tree_add_item(tree, hf_ssh_protocol,
1192                     tvb, offset, protolen, ENC_ASCII|ENC_NA);
1193     offset += linelen;
1194     return offset;
1195 }
1196 
1197 static void
ssh_set_mac_length(struct ssh_peer_data * peer_data)1198 ssh_set_mac_length(struct ssh_peer_data *peer_data)
1199 {
1200     char *size_str;
1201     guint32 size = 0;
1202     char *mac_name = peer_data->mac;
1203     char *strip;
1204 
1205     if (!mac_name)
1206         return;
1207 
1208     /* wmem_strdup() never returns NULL */
1209     mac_name = wmem_strdup(NULL, (const gchar *)mac_name);
1210 
1211     /* strip trailing "-etm@openssh.com" or "@openssh.com" */
1212     strip = strstr(mac_name, "-etm@openssh.com");
1213     if (strip) {
1214         peer_data->length_is_plaintext = 1;
1215         *strip = '\0';
1216     }
1217     else {
1218         strip = strstr(mac_name, "@openssh.com");
1219         if (strip) *strip = '\0';
1220     }
1221 
1222     size_str = g_strrstr(mac_name, "-");
1223     if (size_str && ws_strtou32(size_str + 1, NULL, &size) && size > 0 && size % 8 == 0) {
1224         peer_data->mac_length = size / 8;
1225     }
1226     else if (strcmp(mac_name, "hmac-sha1") == 0) {
1227         peer_data->mac_length = 20;
1228     }
1229     else if (strcmp(mac_name, "hmac-md5") == 0) {
1230         peer_data->mac_length = 16;
1231     }
1232     else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
1233         peer_data->mac_length = 20;
1234     }
1235     else if (strcmp(mac_name, "none") == 0) {
1236         peer_data->mac_length = 0;
1237     }
1238 
1239     wmem_free(NULL, mac_name);
1240 }
1241 
ssh_set_kex_specific_dissector(struct ssh_flow_data * global_data)1242 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
1243 {
1244     const char *kex_name = global_data->kex;
1245 
1246     if (!kex_name) return;
1247 
1248     if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
1249         strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
1250     {
1251         global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
1252     }
1253     else if (g_str_has_prefix(kex_name, "ecdh-sha2-") ||
1254         strcmp(kex_name, "curve25519-sha256@libssh.org") == 0 ||
1255         strcmp(kex_name, "curve25519-sha256") == 0 ||
1256         strcmp(kex_name, "curve448-sha512") == 0)
1257     {
1258         global_data->kex_specific_dissector = ssh_dissect_kex_ecdh;
1259     }
1260 }
1261 
1262 static gint
ssh_gslist_compare_strings(gconstpointer a,gconstpointer b)1263 ssh_gslist_compare_strings(gconstpointer a, gconstpointer b)
1264 {
1265     if (a == NULL && b == NULL)
1266         return 0;
1267     if (a == NULL)
1268         return -1;
1269     if (b == NULL)
1270         return 1;
1271     return strcmp((const char*)a, (const char*)b);
1272 }
1273 
1274 /* expects that *result is NULL */
1275 static void
ssh_choose_algo(gchar * client,gchar * server,gchar ** result)1276 ssh_choose_algo(gchar *client, gchar *server, gchar **result)
1277 {
1278     gchar **server_strings = NULL;
1279     gchar **client_strings = NULL;
1280     gchar **step;
1281     GSList *server_list = NULL;
1282 
1283     if (!client || !server || !result || *result)
1284         return;
1285 
1286     server_strings = g_strsplit(server, ",", 0);
1287     for (step = server_strings; *step; step++) {
1288         server_list = g_slist_append(server_list, *step);
1289     }
1290 
1291     client_strings = g_strsplit(client, ",", 0);
1292     for (step = client_strings; *step; step++) {
1293         GSList *agreed;
1294         if ((agreed = g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
1295             *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data);
1296             break;
1297         }
1298     }
1299 
1300     g_strfreev(client_strings);
1301     g_slist_free(server_list);
1302     g_strfreev(server_strings);
1303 }
1304 
1305 static int
ssh_dissect_key_init(tvbuff_t * tvb,int offset,proto_tree * tree,int is_response,struct ssh_flow_data * global_data)1306 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
1307         int is_response, struct ssh_flow_data *global_data)
1308 {
1309     int start_offset = offset;
1310     int payload_length;
1311     wmem_strbuf_t *hassh_algo;
1312     gchar  *hassh;
1313 
1314     proto_item *tf, *ti;
1315     proto_tree *key_init_tree;
1316 
1317     struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1318 
1319     key_init_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
1320     proto_tree_add_item(key_init_tree, hf_ssh_cookie,
1321                     tvb, offset, 16, ENC_NA);
1322     offset += 16;
1323 
1324     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1325         hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
1326         &peer_data->kex_proposal);
1327     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1328         hf_ssh_server_host_key_algorithms_length,
1329         hf_ssh_server_host_key_algorithms, NULL);
1330     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1331         hf_ssh_encryption_algorithms_client_to_server_length,
1332         hf_ssh_encryption_algorithms_client_to_server,
1333         &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1334     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1335         hf_ssh_encryption_algorithms_server_to_client_length,
1336         hf_ssh_encryption_algorithms_server_to_client,
1337         &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1338     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1339         hf_ssh_mac_algorithms_client_to_server_length,
1340         hf_ssh_mac_algorithms_client_to_server,
1341         &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1342     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1343         hf_ssh_mac_algorithms_server_to_client_length,
1344         hf_ssh_mac_algorithms_server_to_client,
1345         &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1346     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1347         hf_ssh_compression_algorithms_client_to_server_length,
1348         hf_ssh_compression_algorithms_client_to_server,
1349         &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1350     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1351         hf_ssh_compression_algorithms_server_to_client_length,
1352         hf_ssh_compression_algorithms_server_to_client,
1353         &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1354     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1355         hf_ssh_languages_client_to_server_length,
1356         hf_ssh_languages_client_to_server, NULL);
1357     offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1358         hf_ssh_languages_server_to_client_length,
1359         hf_ssh_languages_server_to_client, NULL);
1360 
1361     proto_tree_add_item(key_init_tree, hf_ssh_first_kex_packet_follows,
1362         tvb, offset, 1, ENC_BIG_ENDIAN);
1363     offset+=1;
1364 
1365     proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
1366         tvb, offset, 4, ENC_NA);
1367     offset+=4;
1368 
1369     hassh_algo = wmem_strbuf_new(wmem_packet_scope(), "");
1370     if(!is_response) {
1371         wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL],
1372                 peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL], peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1373         hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
1374         ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
1375         proto_item_set_generated(ti);
1376         ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh, tvb, offset, 0, hassh);
1377         proto_item_set_generated(ti);
1378         g_free(hassh);
1379     } else {
1380         wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL],
1381                 peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL], peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1382         hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
1383         ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
1384         proto_item_set_generated(ti);
1385         ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver, tvb, offset, 0, hassh);
1386         proto_item_set_generated(ti);
1387         g_free(hassh);
1388     }
1389 
1390     if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
1391         global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
1392         !global_data->kex)
1393     {
1394         /* Note: we're ignoring first_kex_packet_follows. */
1395         ssh_choose_algo(
1396             global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
1397             global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
1398             &global_data->kex);
1399         ssh_set_kex_specific_dissector(global_data);
1400     }
1401 
1402     payload_length = offset - start_offset;
1403 
1404     if (tf != NULL) {
1405         proto_item_set_len(tf, payload_length);
1406     }
1407 
1408 #ifdef SSH_DECRYPTION_SUPPORTED
1409     // I_C / I_S (client and server SSH_MSG_KEXINIT payload) RFC4253 4.2
1410     gchar *data = (gchar *)wmem_alloc(wmem_packet_scope(), payload_length + 1);
1411     tvb_memcpy(tvb, data + 1, start_offset, payload_length);
1412     data[0] = SSH_MSG_KEXINIT;
1413     ssh_hash_buffer_put_string(global_data->kex_hash_buffer, data,
1414             payload_length + 1);
1415 #endif
1416 
1417     return offset;
1418 }
1419 
1420 static int
ssh_dissect_proposal(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_index_length,int hf_index_value,char ** store)1421 ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
1422              int hf_index_length, int hf_index_value, char **store)
1423 {
1424     guint32 len = tvb_get_ntohl(tvb, offset);
1425     proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
1426     offset += 4;
1427 
1428     proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
1429                 ENC_ASCII);
1430     if (store)
1431         *store = (char *) tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
1432     offset += len;
1433 
1434     return offset;
1435 }
1436 
1437 #ifdef SSH_DECRYPTION_SUPPORTED
1438 static void
ssh_keylog_read_file(void)1439 ssh_keylog_read_file(void)
1440 {
1441     if (!pref_keylog_file || !*pref_keylog_file) {
1442         ws_debug("no keylog file preference set");
1443         return;
1444     }
1445 
1446     if (ssh_keylog_file && file_needs_reopen(ws_fileno(ssh_keylog_file),
1447                 pref_keylog_file)) {
1448         ssh_keylog_reset();
1449     }
1450 
1451     if (!ssh_keylog_file) {
1452         ssh_keylog_file = ws_fopen(pref_keylog_file, "r");
1453         if (!ssh_keylog_file) {
1454             ws_debug("ssh: failed to open key log file %s: %s",
1455                     pref_keylog_file, g_strerror(errno));
1456             return;
1457         }
1458     }
1459 
1460     /* File format: each line follows the format "<type> <key>".
1461      * For available <type>s, see below. <key> is the hex-encoded key (64
1462      * characters).
1463      *
1464      * Example:
1465      *  curve25519 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
1466      */
1467     for (;;) {
1468         char buf[512];
1469 
1470         if (!fgets(buf, sizeof(buf), ssh_keylog_file)) {
1471             if (ferror(ssh_keylog_file)) {
1472                 ws_debug("Error while reading %s, closing it.", pref_keylog_file);
1473                 ssh_keylog_reset();
1474             }
1475             break;
1476         }
1477 
1478         ssh_keylog_process_line(buf);
1479     }
1480 }
1481 
1482 static void
ssh_keylog_process_line(char * line)1483 ssh_keylog_process_line(char *line)
1484 {
1485     ws_debug("ssh: process line: %s", line);
1486 
1487     gchar **split = g_strsplit(line, " ", 2);
1488     gchar *key, *value;
1489     int key_len;
1490 
1491     if (g_strv_length(split) != 2) {
1492         ws_debug("ssh keylog: invalid format");
1493         g_strfreev(split);
1494         return;
1495     }
1496 
1497     key = split[0];
1498     value = split[1];
1499 
1500     if (!strcmp(key, "curve25519")) {
1501         key_len = 32;
1502     } else {
1503         ws_debug("ssh: key exchange method not supported");
1504         g_strfreev(split);
1505         return;
1506     }
1507 
1508     gchar hexbyte[3] = {0, 0, 0};
1509     guint8 c;
1510     guint8 *converted = g_new(guint8, key_len);
1511 
1512     for (int i = 0; i < key_len; i ++) {
1513         hexbyte[0] = value[i * 2];
1514         hexbyte[1] = value[i * 2 + 1];
1515 
1516         if (!ws_hexstrtou8(hexbyte, NULL, &c)) {
1517             ws_debug("ssh: can't process key, invalid hex number: %s", hexbyte);
1518             g_free(converted);
1519             g_strfreev(split);
1520             return;
1521         }
1522 
1523         converted[i] = c;
1524     }
1525 
1526     ssh_keylog_add_keys(converted, key_len, key);
1527     g_free(converted);
1528     g_strfreev(split);
1529 }
1530 
1531 static void
ssh_keylog_reset(void)1532 ssh_keylog_reset(void)
1533 {
1534     if (ssh_keylog_file) {
1535         fclose(ssh_keylog_file);
1536         ssh_keylog_file = NULL;
1537     }
1538 }
1539 
1540 static guint
ssh_kex_type(char * type)1541 ssh_kex_type(char *type)
1542 {
1543     if (type && g_str_has_prefix(type, "curve25519")) {
1544         return SSH_KEX_CURVE25519;
1545     }
1546 
1547     return 0;
1548 }
1549 
1550 static void
ssh_keylog_add_keys(guint8 * priv,guint priv_length,gchar * type_string)1551 ssh_keylog_add_keys(guint8 *priv, guint priv_length, gchar *type_string)
1552 {
1553     guint type = ssh_kex_type(type_string);
1554     ssh_kex_pub_key *pub = ssh_kex_make_pub_key(NULL, priv_length, type);
1555 
1556     if (SSH_KEX_CURVE25519 == type) {
1557         if (crypto_scalarmult_curve25519_base(pub->data, priv)) {
1558             ws_debug("cannot compute curve25519 public key");
1559             return;
1560         }
1561     } else {
1562         ws_debug("key type %s not supported", type_string);
1563         return;
1564     }
1565 
1566     if (!wmem_map_contains(ssh_kex_keys, pub)) {
1567         ssh_kex_key *value = ssh_kex_make_key(NULL, priv_length);
1568         if (!value) {
1569             ws_debug("invalid key length %u", priv_length);
1570             return;
1571         }
1572         memcpy(value->data, priv, priv_length);
1573         wmem_map_insert(ssh_kex_keys, pub, value);
1574     }
1575 }
1576 
1577 // This was the largest valid value I (gcc) could find.
1578 // https://github.com/openssh/openssh-portable/blob/0a4a5571ada76b1b012bec9cf6ad1203fc19ec8d/sshkey.c#L1589
1579 #define MAX_SSH_KEY_BYTES 16384
1580 static ssh_kex_key *
ssh_kex_make_key(guint8 * data,guint length)1581 ssh_kex_make_key(guint8 *data, guint length)
1582 {
1583     if (length >= MAX_SSH_KEY_BYTES) {
1584         return NULL;
1585     }
1586 
1587     ssh_kex_key *key = wmem_new0(wmem_file_scope(), ssh_kex_key);
1588     key->data = (guint8 *)wmem_alloc0(wmem_file_scope(), length);
1589 
1590     if (data) {
1591         memcpy(key->data, data, length);
1592     }
1593 
1594     key->length = length;
1595     return key;
1596 }
1597 
1598 static ssh_kex_pub_key *
ssh_kex_make_pub_key(guint8 * data,guint length,gchar type)1599 ssh_kex_make_pub_key(guint8 *data, guint length, gchar type)
1600 {
1601     if (length >= MAX_SSH_KEY_BYTES) {
1602         return NULL;
1603     }
1604 
1605     ssh_kex_pub_key *key = wmem_new0(wmem_file_scope(), ssh_kex_pub_key);
1606     key->data = (guint8 *)wmem_alloc0(wmem_file_scope(), length);
1607 
1608     if (data) {
1609         memcpy(key->data, data, length);
1610     }
1611 
1612     key->length = length;
1613     key->type = type;
1614     return key;
1615 }
1616 
1617 static void
ssh_read_e(tvbuff_t * tvb,int offset,struct ssh_flow_data * global_data)1618 ssh_read_e(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
1619 {
1620     // store the client's public part (e) for later usage
1621     guint length = tvb_get_ntohl(tvb, offset);
1622     guint type = ssh_kex_type(global_data->kex);
1623     ssh_kex_pub_key *kex = ssh_kex_make_pub_key(NULL, length, type);
1624     if (!kex) {
1625         ws_debug("invalid key length %u", length);
1626         return;
1627     }
1628     global_data->kex_e = kex;
1629     tvb_memcpy(tvb, global_data->kex_e->data, offset + 4, length);
1630 }
1631 
1632 static void
ssh_keylog_compute_hash(tvbuff_t * tvb,int offset,struct ssh_flow_data * global_data)1633 ssh_keylog_compute_hash(tvbuff_t *tvb, int offset,
1634         struct ssh_flow_data *global_data)
1635 {
1636     /*
1637      * This computation is defined differently for each key exchange method:
1638      * https://tools.ietf.org/html/rfc4253#page-23
1639      * https://tools.ietf.org/html/rfc5656#page-8
1640      * https://tools.ietf.org/html/rfc4419#page-4
1641      * All key exchange methods:
1642      * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16
1643      */
1644     if (global_data->kex_hash_buffer == NULL) {
1645         return;
1646     }
1647 
1648     gcry_md_hd_t hd;
1649     ssh_kex_key *secret, *priv;
1650     ssh_kex_pub_key kex_f;
1651     int length;
1652     // TODO support other key exchange algorithms than curve25519-sha256
1653     guint hash_len = 32;
1654 
1655     ssh_keylog_read_file();
1656 
1657     if (global_data->kex_e == NULL) {
1658         return;
1659     }
1660 
1661     length = tvb_get_ntohl(tvb, offset);
1662     kex_f.length = length;
1663     kex_f.data = (gchar *)tvb_memdup(wmem_packet_scope(), tvb, offset + 4, length);
1664     kex_f.type = global_data->kex_e->type;
1665     priv = (ssh_kex_key *)wmem_map_lookup(ssh_kex_keys, global_data->kex_e);
1666 
1667     if (!priv) {
1668         priv = (ssh_kex_key *)wmem_map_lookup(ssh_kex_keys, &kex_f);
1669 
1670         if (!priv) {
1671             ws_debug("ssh decryption: private key not available");
1672             return;
1673 
1674         // we have the server's private key
1675         } else {
1676             secret = ssh_kex_shared_secret(global_data->kex_e, priv);
1677         }
1678 
1679     // we have the client's private key
1680     } else {
1681         secret = ssh_kex_shared_secret(&kex_f, priv);
1682     }
1683 
1684     if (!secret) {
1685         return;
1686     }
1687 
1688     ssh_hash_buffer_put_string(global_data->kex_hash_buffer,
1689             global_data->kex_e->data, length);
1690     ssh_hash_buffer_put_string(global_data->kex_hash_buffer, kex_f.data, length);
1691 
1692     // shared secret data needs to be written as an mpint, and we need it later
1693     if (secret->data[0] & 0x80) {
1694         gchar *tmp = (gchar *)wmem_alloc0(wmem_packet_scope(), length + 1);
1695         memcpy(tmp + 1, secret->data, length);
1696         tmp[0] = 0;
1697         secret->data = tmp;
1698         secret->length = length + 1;
1699         ssh_hash_buffer_put_string(global_data->kex_hash_buffer, secret->data,
1700                 length + 1);
1701     } else
1702         ssh_hash_buffer_put_string(global_data->kex_hash_buffer, secret->data,
1703                 length);
1704 
1705     gchar *exchange_hash = (gchar *)wmem_alloc0(wmem_file_scope(), hash_len);
1706     gcry_md_open(&hd, GCRY_MD_SHA256, 0);
1707     gcry_md_write(hd, wmem_array_get_raw(global_data->kex_hash_buffer),
1708             wmem_array_get_count(global_data->kex_hash_buffer));
1709     memcpy(exchange_hash, gcry_md_read(hd, 0), hash_len);
1710     gcry_md_close(hd);
1711     global_data->kex_hash_buffer = NULL;
1712     ssh_derive_symmetric_keys(secret, exchange_hash, hash_len, global_data);
1713 }
1714 
1715 // the purpose of this function is to deal with all different kex methods
1716 static ssh_kex_key *
ssh_kex_shared_secret(ssh_kex_pub_key * pub,ssh_kex_key * priv)1717 ssh_kex_shared_secret(ssh_kex_pub_key *pub, ssh_kex_key *priv)
1718 {
1719     ssh_kex_key *secret = ssh_kex_make_key(NULL, pub->length);
1720     if (!secret) {
1721         ws_debug("invalid key length %u", pub->length);
1722         return NULL;
1723     }
1724 
1725     if (crypto_scalarmult_curve25519(secret->data, priv->data, pub->data)) {
1726         ws_debug("curve25519: can't compute shared secret");
1727         return NULL;
1728     }
1729 
1730     return secret;
1731 }
1732 
1733 static gchar *
ssh_string(const gchar * string,guint length)1734 ssh_string(const gchar *string, guint length)
1735 {
1736     gchar *ssh_string = (gchar *)wmem_alloc(wmem_packet_scope(), length + 4);
1737     ssh_string[0] = (length >> 24) & 0xff;
1738     ssh_string[1] = (length >> 16) & 0xff;
1739     ssh_string[2] = (length >> 8) & 0xff;
1740     ssh_string[3] = length & 0xff;
1741     memcpy(ssh_string + 4, string, length);
1742     return ssh_string;
1743 }
1744 
1745 static void
ssh_hash_buffer_put_string(wmem_array_t * buffer,const gchar * string,guint length)1746 ssh_hash_buffer_put_string(wmem_array_t *buffer, const gchar *string,
1747         guint length)
1748 {
1749     if (!buffer) {
1750         return;
1751     }
1752 
1753     gchar *string_with_length = ssh_string(string, length);
1754     wmem_array_append(buffer, string_with_length, length + 4);
1755 }
1756 
ssh_derive_symmetric_keys(ssh_kex_key * secret,gchar * exchange_hash,guint hash_length,struct ssh_flow_data * global_data)1757 static void ssh_derive_symmetric_keys(ssh_kex_key *secret, gchar *exchange_hash,
1758         guint hash_length, struct ssh_flow_data *global_data)
1759 {
1760     ssh_enc_key keys[6];
1761 
1762     if (!global_data->session_id) {
1763         global_data->session_id = exchange_hash;
1764         global_data->session_id_length = hash_length;
1765     }
1766 
1767     for (int i = 0; i < 6; i ++) {
1768         ssh_derive_symmetric_key(secret, exchange_hash, hash_length,
1769                 'A' + i, &keys[i], global_data);
1770     }
1771 }
1772 
ssh_derive_symmetric_key(ssh_kex_key * secret,gchar * exchange_hash,guint hash_length,gchar id,ssh_enc_key * result_key,struct ssh_flow_data * global_data)1773 static void ssh_derive_symmetric_key(ssh_kex_key *secret, gchar *exchange_hash,
1774         guint hash_length, gchar id, ssh_enc_key *result_key,
1775         struct ssh_flow_data *global_data)
1776 {
1777     gcry_md_hd_t hd;
1778     guint len = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1779 
1780     // required size of key depends on cipher used. chacha20 wants 64 bytes
1781     guint need = 64;
1782     result_key->data = (guchar *)wmem_alloc(wmem_file_scope(), need);
1783 
1784     gchar *secret_with_length = ssh_string(secret->data, secret->length);
1785 
1786     if (gcry_md_open(&hd, GCRY_MD_SHA256, 0) == 0) {
1787         gcry_md_write(hd, secret_with_length, secret->length + 4);
1788         gcry_md_write(hd, exchange_hash, hash_length);
1789         gcry_md_putc(hd, id);
1790         gcry_md_write(hd, global_data->session_id, hash_length);
1791         memcpy(result_key->data, gcry_md_read(hd, 0), len);
1792         gcry_md_close(hd);
1793     }
1794 
1795     // expand key
1796     for (guint have = len; have < need; have += len) {
1797         if (gcry_md_open(&hd, GCRY_MD_SHA256, 0) == 0) {
1798             gcry_md_write(hd, secret_with_length, secret->length + 4);
1799             gcry_md_write(hd, exchange_hash, hash_length);
1800             gcry_md_write(hd, result_key->data, len);
1801             guint add_length = MIN(len, need - have);
1802             memcpy(result_key->data+have, gcry_md_read(hd, 0), add_length);
1803             gcry_md_close(hd);
1804         }
1805     }
1806 
1807     result_key->length = need;
1808 }
1809 
1810 static guint
ssh_kex_pub_key_hash(gconstpointer v1)1811 ssh_kex_pub_key_hash(gconstpointer v1)
1812 {
1813     const ssh_kex_pub_key *key1 = (const ssh_kex_pub_key *)v1;
1814     return wmem_strong_hash(key1->data, key1->length);
1815 }
1816 
1817 static gboolean
ssh_kex_pub_key_equal(gconstpointer v1,gconstpointer v2)1818 ssh_kex_pub_key_equal(gconstpointer v1, gconstpointer v2)
1819 {
1820     const ssh_kex_pub_key *key1 = (const ssh_kex_pub_key *)v1;
1821     const ssh_kex_pub_key *key2 = (const ssh_kex_pub_key *)v2;
1822     return key1->type == key2->type && key1->length == key2->length &&
1823         !memcmp(key1->data, key2->data, key1->length);
1824 }
1825 #endif /* SSH_DECRYPTION_SUPPORTED */
1826 
1827 void
proto_register_ssh(void)1828 proto_register_ssh(void)
1829 {
1830     static hf_register_info hf[] = {
1831         { &hf_ssh_protocol,
1832           { "Protocol",  "ssh.protocol",
1833             FT_STRING, BASE_NONE, NULL, 0x0,
1834             NULL, HFILL }},
1835 
1836         { &hf_ssh_packet_length,
1837           { "Packet Length",      "ssh.packet_length",
1838             FT_UINT32, BASE_DEC, NULL,  0x0,
1839             NULL, HFILL }},
1840 
1841         { &hf_ssh_packet_length_encrypted,
1842           { "Packet Length (encrypted)",      "ssh.packet_length_encrypted",
1843             FT_BYTES, BASE_NONE, NULL,  0x0,
1844             NULL, HFILL }},
1845 
1846         { &hf_ssh_padding_length,
1847           { "Padding Length",  "ssh.padding_length",
1848             FT_UINT8, BASE_DEC, NULL, 0x0,
1849             NULL, HFILL }},
1850 
1851         { &hf_ssh_payload,
1852           { "Payload",  "ssh.payload",
1853             FT_BYTES, BASE_NONE, NULL, 0x0,
1854             NULL, HFILL }},
1855 
1856         { &hf_ssh_encrypted_packet,
1857           { "Encrypted Packet",  "ssh.encrypted_packet",
1858             FT_BYTES, BASE_NONE, NULL, 0x0,
1859             NULL, HFILL }},
1860 
1861         { &hf_ssh_padding_string,
1862           { "Padding String",  "ssh.padding_string",
1863             FT_BYTES, BASE_NONE, NULL, 0x0,
1864             NULL, HFILL }},
1865 
1866         { &hf_ssh_mac_string,
1867           { "MAC",  "ssh.mac",
1868             FT_BYTES, BASE_NONE, NULL, 0x0,
1869             "Message authentication code", HFILL }},
1870 
1871         { &hf_ssh_direction,
1872           { "Direction", "ssh.direction",
1873             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1874             "Message direction", HFILL }},
1875 
1876         { &hf_ssh_msg_code,
1877           { "Message Code",  "ssh.message_code",
1878             FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
1879             NULL, HFILL }},
1880 
1881         { &hf_ssh2_msg_code,
1882           { "Message Code",  "ssh.message_code",
1883             FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
1884             NULL, HFILL }},
1885 
1886         { &hf_ssh2_kex_dh_msg_code,
1887           { "Message Code",  "ssh.message_code",
1888             FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
1889             NULL, HFILL }},
1890 
1891         { &hf_ssh2_kex_dh_gex_msg_code,
1892           { "Message Code",  "ssh.message_code",
1893             FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
1894             NULL, HFILL }},
1895 
1896         { &hf_ssh2_kex_ecdh_msg_code,
1897           { "Message Code",  "ssh.message_code",
1898             FT_UINT8, BASE_DEC, VALS(ssh2_kex_ecdh_msg_vals), 0x0,
1899             NULL, HFILL }},
1900 
1901         { &hf_ssh_cookie,
1902           { "Cookie",  "ssh.cookie",
1903             FT_BYTES, BASE_NONE, NULL, 0x0,
1904             NULL, HFILL }},
1905 
1906         { &hf_ssh_kex_algorithms,
1907           { "kex_algorithms string",         "ssh.kex_algorithms",
1908             FT_STRING, BASE_NONE, NULL, 0x0,
1909             NULL, HFILL }},
1910 
1911         { &hf_ssh_server_host_key_algorithms,
1912           { "server_host_key_algorithms string",         "ssh.server_host_key_algorithms",
1913             FT_STRING, BASE_NONE, NULL, 0x0,
1914             NULL, HFILL }},
1915 
1916         { &hf_ssh_encryption_algorithms_client_to_server,
1917           { "encryption_algorithms_client_to_server string",         "ssh.encryption_algorithms_client_to_server",
1918             FT_STRING, BASE_NONE, NULL, 0x0,
1919             NULL, HFILL }},
1920 
1921         { &hf_ssh_encryption_algorithms_server_to_client,
1922           { "encryption_algorithms_server_to_client string",         "ssh.encryption_algorithms_server_to_client",
1923             FT_STRING, BASE_NONE, NULL, 0x0,
1924             NULL, HFILL }},
1925 
1926         { &hf_ssh_mac_algorithms_client_to_server,
1927           { "mac_algorithms_client_to_server string",         "ssh.mac_algorithms_client_to_server",
1928             FT_STRING, BASE_NONE, NULL, 0x0,
1929             NULL, HFILL }},
1930 
1931         { &hf_ssh_mac_algorithms_server_to_client,
1932           { "mac_algorithms_server_to_client string",         "ssh.mac_algorithms_server_to_client",
1933             FT_STRING, BASE_NONE, NULL, 0x0,
1934             NULL, HFILL }},
1935 
1936         { &hf_ssh_compression_algorithms_client_to_server,
1937           { "compression_algorithms_client_to_server string",         "ssh.compression_algorithms_client_to_server",
1938             FT_STRING, BASE_NONE, NULL, 0x0,
1939             NULL, HFILL }},
1940 
1941         { &hf_ssh_compression_algorithms_server_to_client,
1942           { "compression_algorithms_server_to_client string",         "ssh.compression_algorithms_server_to_client",
1943             FT_STRING, BASE_NONE, NULL, 0x0,
1944             NULL, HFILL }},
1945 
1946         { &hf_ssh_languages_client_to_server,
1947           { "languages_client_to_server string",         "ssh.languages_client_to_server",
1948             FT_STRING, BASE_NONE, NULL, 0x0,
1949             NULL, HFILL }},
1950 
1951         { &hf_ssh_languages_server_to_client,
1952           { "languages_server_to_client string",         "ssh.languages_server_to_client",
1953             FT_STRING, BASE_NONE, NULL, 0x0,
1954             NULL, HFILL }},
1955 
1956         { &hf_ssh_kex_algorithms_length,
1957           { "kex_algorithms length",         "ssh.kex_algorithms_length",
1958             FT_UINT32, BASE_DEC, NULL, 0x0,
1959             NULL, HFILL }},
1960 
1961         { &hf_ssh_server_host_key_algorithms_length,
1962           { "server_host_key_algorithms length",         "ssh.server_host_key_algorithms_length",
1963             FT_UINT32, BASE_DEC, NULL, 0x0,
1964             NULL, HFILL }},
1965 
1966         { &hf_ssh_encryption_algorithms_client_to_server_length,
1967           { "encryption_algorithms_client_to_server length",         "ssh.encryption_algorithms_client_to_server_length",
1968             FT_UINT32, BASE_DEC, NULL, 0x0,
1969             NULL, HFILL }},
1970 
1971         { &hf_ssh_encryption_algorithms_server_to_client_length,
1972           { "encryption_algorithms_server_to_client length",         "ssh.encryption_algorithms_server_to_client_length",
1973             FT_UINT32, BASE_DEC, NULL, 0x0,
1974             NULL, HFILL }},
1975 
1976         { &hf_ssh_mac_algorithms_client_to_server_length,
1977           { "mac_algorithms_client_to_server length",         "ssh.mac_algorithms_client_to_server_length",
1978             FT_UINT32, BASE_DEC, NULL, 0x0,
1979             NULL, HFILL }},
1980 
1981         { &hf_ssh_mac_algorithms_server_to_client_length,
1982           { "mac_algorithms_server_to_client length",         "ssh.mac_algorithms_server_to_client_length",
1983             FT_UINT32, BASE_DEC, NULL, 0x0,
1984             NULL, HFILL }},
1985 
1986         { &hf_ssh_compression_algorithms_client_to_server_length,
1987           { "compression_algorithms_client_to_server length",         "ssh.compression_algorithms_client_to_server_length",
1988             FT_UINT32, BASE_DEC, NULL, 0x0,
1989             NULL, HFILL }},
1990 
1991         { &hf_ssh_compression_algorithms_server_to_client_length,
1992           { "compression_algorithms_server_to_client length",         "ssh.compression_algorithms_server_to_client_length",
1993             FT_UINT32, BASE_DEC, NULL, 0x0,
1994             NULL, HFILL }},
1995 
1996         { &hf_ssh_languages_client_to_server_length,
1997           { "languages_client_to_server length",         "ssh.languages_client_to_server_length",
1998             FT_UINT32, BASE_DEC, NULL, 0x0,
1999             NULL, HFILL }},
2000 
2001         { &hf_ssh_languages_server_to_client_length,
2002           { "languages_server_to_client length",         "ssh.languages_server_to_client_length",
2003             FT_UINT32, BASE_DEC, NULL, 0x0,
2004             NULL, HFILL }},
2005 
2006         { &hf_ssh_first_kex_packet_follows,
2007           { "First KEX Packet Follows",      "ssh.first_kex_packet_follows",
2008             FT_UINT8, BASE_DEC, NULL, 0x0,
2009             NULL, HFILL }},
2010 
2011         { &hf_ssh_kex_reserved,
2012           { "Reserved",  "ssh.kex.reserved",
2013             FT_BYTES, BASE_NONE, NULL, 0x0,
2014             NULL, HFILL }},
2015 
2016         { &hf_ssh_kex_hassh_algo,
2017           { "hasshAlgorithms",  "ssh.kex.hassh_algorithms",
2018             FT_STRING, BASE_NONE, NULL, 0x0,
2019             NULL, HFILL }},
2020 
2021         { &hf_ssh_kex_hassh,
2022           { "hassh",  "ssh.kex.hassh",
2023             FT_STRING, BASE_NONE, NULL, 0x0,
2024             NULL, HFILL }},
2025 
2026         { &hf_ssh_kex_hasshserver_algo,
2027           { "hasshServerAlgorithms",  "ssh.kex.hasshserver_algorithms",
2028             FT_STRING, BASE_NONE, NULL, 0x0,
2029             NULL, HFILL }},
2030 
2031         { &hf_ssh_kex_hasshserver,
2032           { "hasshServer",  "ssh.kex.hasshserver",
2033             FT_STRING, BASE_NONE, NULL, 0x0,
2034             NULL, HFILL }},
2035 
2036         { &hf_ssh_hostkey_length,
2037           { "Host key length",         "ssh.host_key.length",
2038             FT_UINT32, BASE_DEC, NULL, 0x0,
2039             NULL, HFILL }},
2040 
2041         { &hf_ssh_hostkey_type_length,
2042           { "Host key type length",         "ssh.host_key.type_length",
2043             FT_UINT32, BASE_DEC, NULL, 0x0,
2044             NULL, HFILL }},
2045 
2046         { &hf_ssh_hostkey_type,
2047           { "Host key type",         "ssh.host_key.type",
2048             FT_STRING, BASE_NONE, NULL, 0x0,
2049             NULL, HFILL }},
2050 
2051         { &hf_ssh_hostkey_data,
2052           { "Host key data",         "ssh.host_key.data",
2053             FT_BYTES, BASE_NONE, NULL, 0x0,
2054             NULL, HFILL }},
2055 
2056         { &hf_ssh_hostkey_rsa_n,
2057           { "RSA modulus (N)",         "ssh.host_key.rsa.n",
2058             FT_BYTES, BASE_NONE, NULL, 0x0,
2059             NULL, HFILL }},
2060 
2061         { &hf_ssh_hostkey_rsa_e,
2062           { "RSA public exponent (e)",         "ssh.host_key.rsa.e",
2063             FT_BYTES, BASE_NONE, NULL, 0x0,
2064             NULL, HFILL }},
2065 
2066         { &hf_ssh_hostkey_dsa_p,
2067           { "DSA prime modulus (p)",  "ssh.host_key.dsa.p",
2068             FT_BYTES, BASE_NONE, NULL, 0x0,
2069             NULL, HFILL }},
2070 
2071         { &hf_ssh_hostkey_dsa_q,
2072           { "DSA prime divisor (q)",  "ssh.host_key.dsa.q",
2073             FT_BYTES, BASE_NONE, NULL, 0x0,
2074             NULL, HFILL }},
2075 
2076         { &hf_ssh_hostkey_dsa_g,
2077           { "DSA subgroup generator (g)",  "ssh.host_key.dsa.g",
2078             FT_BYTES, BASE_NONE, NULL, 0x0,
2079             NULL, HFILL }},
2080 
2081         { &hf_ssh_hostkey_dsa_y,
2082           { "DSA public key (y)",  "ssh.host_key.dsa.y",
2083             FT_BYTES, BASE_NONE, NULL, 0x0,
2084             NULL, HFILL }},
2085 
2086         { &hf_ssh_hostkey_ecdsa_curve_id,
2087           { "ECDSA elliptic curve identifier",  "ssh.host_key.ecdsa.id",
2088             FT_STRING, BASE_NONE, NULL, 0x0,
2089             NULL, HFILL }},
2090 
2091         { &hf_ssh_hostkey_ecdsa_curve_id_length,
2092           { "ECDSA elliptic curve identifier length",  "ssh.host_key.ecdsa.id_length",
2093             FT_UINT32, BASE_DEC, NULL, 0x0,
2094             NULL, HFILL }},
2095 
2096         { &hf_ssh_hostkey_ecdsa_q,
2097           { "ECDSA public key (Q)",  "ssh.host_key.ecdsa.q",
2098             FT_BYTES, BASE_NONE, NULL, 0x0,
2099             NULL, HFILL }},
2100 
2101         { &hf_ssh_hostkey_ecdsa_q_length,
2102           { "ECDSA public key length",  "ssh.host_key.ecdsa.q_length",
2103             FT_UINT32, BASE_DEC, NULL, 0x0,
2104             NULL, HFILL }},
2105 
2106         { &hf_ssh_hostkey_eddsa_key,
2107           { "EdDSA public key",  "ssh.host_key.eddsa.key",
2108             FT_BYTES, BASE_NONE, NULL, 0x0,
2109             NULL, HFILL }},
2110 
2111         { &hf_ssh_hostkey_eddsa_key_length,
2112           { "EdDSA public key length",  "ssh.host_key.eddsa.key_length",
2113             FT_UINT32, BASE_DEC, NULL, 0x0,
2114             NULL, HFILL }},
2115 
2116         { &hf_ssh_kex_h_sig,
2117           { "KEX H signature",         "ssh.kex.h_sig",
2118             FT_BYTES, BASE_NONE, NULL, 0x0,
2119             NULL, HFILL }},
2120 
2121         { &hf_ssh_kex_h_sig_length,
2122           { "KEX H signature length",         "ssh.kex.h_sig_length",
2123             FT_UINT32, BASE_DEC, NULL, 0x0,
2124             NULL, HFILL }},
2125 
2126         { &hf_ssh_dh_e,
2127           { "DH client e",  "ssh.dh.e",
2128             FT_BYTES, BASE_NONE, NULL, 0x0,
2129             NULL, HFILL }},
2130 
2131         { &hf_ssh_dh_f,
2132           { "DH server f",  "ssh.dh.f",
2133             FT_BYTES, BASE_NONE, NULL, 0x0,
2134             NULL, HFILL }},
2135 
2136         { &hf_ssh_dh_gex_min,
2137           { "DH GEX Min",  "ssh.dh_gex.min",
2138             FT_UINT32, BASE_DEC, NULL, 0x0,
2139             "Minimal acceptable group size", HFILL }},
2140 
2141         { &hf_ssh_dh_gex_nbits,
2142           { "DH GEX Number of Bits",  "ssh.dh_gex.nbits",
2143             FT_UINT32, BASE_DEC, NULL, 0x0,
2144             "Preferred group size", HFILL }},
2145 
2146         { &hf_ssh_dh_gex_max,
2147           { "DH GEX Max",  "ssh.dh_gex.max",
2148             FT_UINT32, BASE_DEC, NULL, 0x0,
2149             "Maximal acceptable group size", HFILL }},
2150 
2151         { &hf_ssh_dh_gex_p,
2152           { "DH GEX modulus (P)",  "ssh.dh_gex.p",
2153             FT_BYTES, BASE_NONE, NULL, 0x0,
2154             NULL, HFILL }},
2155 
2156         { &hf_ssh_dh_gex_g,
2157           { "DH GEX base (G)",  "ssh.dh_gex.g",
2158             FT_BYTES, BASE_NONE, NULL, 0x0,
2159             NULL, HFILL }},
2160 
2161         { &hf_ssh_ecdh_q_c,
2162           { "ECDH client's ephemeral public key (Q_C)",  "ssh.ecdh.q_c",
2163             FT_BYTES, BASE_NONE, NULL, 0x0,
2164             NULL, HFILL }},
2165 
2166         { &hf_ssh_ecdh_q_c_length,
2167           { "ECDH client's ephemeral public key length",  "ssh.ecdh.q_c_length",
2168             FT_UINT32, BASE_DEC, NULL,  0x0,
2169             NULL, HFILL }},
2170 
2171         { &hf_ssh_ecdh_q_s,
2172           { "ECDH server's ephemeral public key (Q_S)",  "ssh.ecdh.q_s",
2173             FT_BYTES, BASE_NONE, NULL, 0x0,
2174             NULL, HFILL }},
2175 
2176         { &hf_ssh_ecdh_q_s_length,
2177           { "ECDH server's ephemeral public key length",  "ssh.ecdh.q_s_length",
2178             FT_UINT32, BASE_DEC, NULL,  0x0,
2179             NULL, HFILL }},
2180 
2181         { &hf_ssh_mpint_length,
2182           { "Multi Precision Integer Length",      "ssh.mpint_length",
2183             FT_UINT32, BASE_DEC, NULL,  0x0,
2184             NULL, HFILL }},
2185     };
2186 
2187     static gint *ett[] = {
2188         &ett_ssh,
2189         &ett_key_exchange,
2190         &ett_key_exchange_host_key,
2191         &ett_ssh1,
2192         &ett_ssh2,
2193         &ett_key_init
2194     };
2195 
2196     static ei_register_info ei[] = {
2197         { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
2198     };
2199 
2200     module_t *ssh_module;
2201     expert_module_t *expert_ssh;
2202 
2203     proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
2204     proto_register_field_array(proto_ssh, hf, array_length(hf));
2205     proto_register_subtree_array(ett, array_length(ett));
2206     expert_ssh = expert_register_protocol(proto_ssh);
2207     expert_register_field_array(expert_ssh, ei, array_length(ei));
2208 
2209     ssh_module = prefs_register_protocol(proto_ssh, NULL);
2210     prefs_register_bool_preference(ssh_module, "desegment_buffers",
2211                        "Reassemble SSH buffers spanning multiple TCP segments",
2212                        "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
2213                        "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2214                        &ssh_desegment);
2215 
2216 #ifdef SSH_DECRYPTION_SUPPORTED
2217     prefs_register_filename_preference(ssh_module, "keylog_file", "Key log filename",
2218             "The path to the file which contains a list of key exchange secrets in the following format:\n"
2219             "\"<key-type> <hex-encoded-key>\" (without quotes or leading spaces).\n"
2220             "<key-type> is one of: curve25519. ",
2221             &pref_keylog_file, FALSE);
2222 
2223     ssh_kex_keys = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
2224                                           ssh_kex_pub_key_hash, ssh_kex_pub_key_equal);
2225 #endif
2226 
2227     ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
2228 }
2229 
2230 void
proto_reg_handoff_ssh(void)2231 proto_reg_handoff_ssh(void)
2232 {
2233     dissector_add_uint_range_with_preference("tcp.port", TCP_RANGE_SSH, ssh_handle);
2234     dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
2235     dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
2236 }
2237 
2238 /*
2239  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2240  *
2241  * Local variables:
2242  * c-basic-offset: 4
2243  * tab-width: 8
2244  * indent-tabs-mode: nil
2245  * End:
2246  *
2247  * vi: set shiftwidth=4 tabstop=8 expandtab:
2248  * :indentSize=4:tabSize=8:noTabs=true:
2249  */
2250