chiark / gitweb /
cleanup: Whitespaces fixes, left right and centre.
[tripe] / wireshark / packet-tripe.c
1 /* -*-c-*-
2  *
3  * $Id$
4  *
5  * TrIPE protocol dissector for Wireshark
6  *
7  * (c) 2003 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------*
11  *
12  * This file is part of Trivial IP Encryption (TrIPE).
13  *
14  * TrIPE is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * TrIPE is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with TrIPE; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Header files ------------------------------------------------------*/
30
31 #include "config.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36
37 #include <netinet/in.h>
38
39 #include <glib.h>
40 #include <gmodule.h>
41 #include <wireshark/config.h>
42 #include <wireshark/epan/packet.h>
43 #include <wireshark/epan/prefs.h>
44
45 #include "protocol.h"
46
47 /*----- Static variables --------------------------------------------------*/
48
49 static int proto_tripe = -1;
50
51 static guint hashsz = 20, tagsz = 10, ivsz = 8;
52
53 typedef struct hfmp {
54   int hf, hf_len, hf_val, tt;
55 } hfmp;
56 typedef struct hfge {
57   int hf, hf_len, hf_val, hfx_len, hfx_val, hfy_len, hfy_val, tt;
58 } hfge;
59
60 static int hf_tripe_cat = -1;
61 static int hf_tripe_packet_type = -1;
62 static int hf_tripe_ct = -1;
63 static int hf_tripe_ct_seq = -1;
64 static int hf_tripe_ct_iv = -1;
65 static int hf_tripe_ct_ct = -1;
66 static int hf_tripe_ct_tag = -1;
67 static int hf_tripe_misc_type = -1;
68 static int hf_tripe_misc_payload = -1;
69 static int hf_tripe_kx_type = -1;
70 static hfge hf_tripe_kx_mychal = { -1, -1, -1, -1, -1, -1, -1, -1 };
71 static int hf_tripe_kx_mycookie = -1;
72 static int hf_tripe_kx_yourcookie = -1;
73 static hfmp hf_tripe_kx_check = { -1, -1, -1, -1 };
74 static int hf_tripe_huh = -1;
75
76 static int tt_tripe = -1;
77 static int tt_tripe_ct = -1;
78
79 G_MODULE_EXPORT const gchar version[] = VERSION;
80
81 /*----- Main code ---------------------------------------------------------*/
82
83 static void prefcb(void) { }
84
85 static gint gethash(proto_tree *tt, int hf, tvbuff_t *b, gint off)
86 {
87   proto_tree_add_item(tt, hf, b, off, hashsz, FALSE);
88   return (off + hashsz);
89 }
90
91 static gint getmp(proto_tree *tt, const hfmp *hf, tvbuff_t *b, gint off)
92 {
93   guint16 len = tvb_get_ntohs(b, off);
94   proto_item *ti = proto_tree_add_item(tt, hf->hf, b, off, len + 2, FALSE);
95   tt = proto_item_add_subtree(ti, hf->tt);
96   proto_tree_add_item(tt, hf->hf_len, b, off, 2, FALSE);
97   proto_tree_add_item(tt, hf->hf_val, b, off + 2, len, FALSE);
98   return (off + 2 + len);
99 }
100
101 static gint getge(proto_tree *tt, const hfge *hf, tvbuff_t *b, gint off)
102 {
103   guint16 len = tvb_get_ntohs(b, off), len2;
104   guint r;
105   proto_item *ti;
106   r = tvb_length_remaining(b, off);
107   if (r < 4 + len ||
108       (len2 = tvb_get_ntohs(b, off + 2 + len), r < 4 + len + len2)) {
109     ti = proto_tree_add_item(tt, hf->hf, b, off, len + 2, FALSE);
110     tt = proto_item_add_subtree(ti, hf->tt);
111     proto_tree_add_item(tt, hf->hf_len, b, off, 2, FALSE);
112     proto_tree_add_item(tt, hf->hf_val, b, off + 2, len, FALSE);
113     r = off + len + 2;
114   } else {
115     ti = proto_tree_add_item(tt, hf->hf, b, off, len + len2 + 4, FALSE);
116     tt = proto_item_add_subtree(ti, hf->tt);
117     proto_tree_add_item(tt, hf->hfx_len, b, off, 2, FALSE);
118     proto_tree_add_item(tt, hf->hfx_val, b, off + 2, len, FALSE);
119     proto_tree_add_item(tt, hf->hfy_len, b, off + 2 + len, 2, FALSE);
120     proto_tree_add_item(tt, hf->hfy_val, b, off + 4 + len, len2, FALSE);
121     r = off + len + len2 + 4;
122   }
123   return (r);
124 }
125
126 static void dissect_tripe(tvbuff_t *b, packet_info *p, proto_tree *t)
127 {
128   proto_item *ti;
129   proto_tree *tt;
130   guint8 ty;
131   gint off = 0;
132   guint32 seq;
133
134   /* --- Initialize the summary cells --- */
135
136   if (check_col(p->cinfo, COL_PROTOCOL))
137     col_set_str(p->cinfo, COL_PROTOCOL, "TrIPE");
138   if (check_col(p->cinfo, COL_INFO))
139     col_clear(p->cinfo, COL_INFO);
140   ty = tvb_get_guint8(b, 0);
141   if (check_col(p->cinfo, COL_INFO)) {
142     col_clear(p->cinfo, COL_INFO);
143     switch (ty & MSG_CATMASK) {
144       case MSG_PACKET:
145         switch (ty & MSG_TYPEMASK) {
146           case 0:
147             col_set_str(p->cinfo, COL_INFO, "Packet data");
148             break;
149           default:
150             col_add_fstr(p->cinfo, COL_INFO,
151                          "Packet data, unknown type code %u",
152                          ty & MSG_TYPEMASK);
153             break;
154         }
155         break;
156       case MSG_KEYEXCH:
157         switch (ty & MSG_TYPEMASK) {
158           case KX_PRECHAL:
159             col_set_str(p->cinfo, COL_INFO, "Key exchange, prechallenge");
160             break;
161           case KX_CHAL:
162             col_set_str(p->cinfo, COL_INFO, "Key exchange, challenge");
163             break;
164           case KX_REPLY:
165             col_set_str(p->cinfo, COL_INFO, "Key exchange, reply");
166             break;
167           case KX_SWITCH:
168             col_set_str(p->cinfo, COL_INFO, "Key exchange, switch request");
169             break;
170           case KX_SWITCHOK:
171             col_set_str(p->cinfo, COL_INFO, "Key exchange, switch response");
172             break;
173           default:
174             col_add_fstr(p->cinfo, COL_INFO,
175                          "Key exchange, unknown type code %u",
176                          ty & MSG_TYPEMASK);
177             break;
178         }
179         break;
180       case MSG_MISC:
181         switch (ty & MSG_TYPEMASK) {
182           case MISC_NOP:
183             col_set_str(p->cinfo, COL_INFO, "Miscellaneous, no-operation");
184             break;
185           case MISC_PING:
186             col_set_str(p->cinfo, COL_INFO, "Miscellaneous, transport ping");
187             break;
188           case MISC_PONG:
189             col_set_str(p->cinfo, COL_INFO,
190                         "Miscellaneous, transport ping reply");
191             break;
192           case MISC_EPING:
193             col_set_str(p->cinfo, COL_INFO, "Miscellaneous, encrypted ping");
194             break;
195           case MISC_EPONG:
196             col_set_str(p->cinfo, COL_INFO,
197                         "Miscellaneous, encrypted ping reply");
198             break;
199           case MISC_GREET:
200             col_set_str(p->cinfo, COL_INFO,
201                         "Miscellaneous, greeting");
202             break;
203           default:
204             col_add_fstr(p->cinfo, COL_INFO,
205                          "Miscellaneous, unknown type code %u",
206                          ty & MSG_TYPEMASK);
207             break;
208         }
209         break;
210       default:
211         col_add_fstr(p->cinfo, COL_INFO,
212                      "Unknown category code %u, unknown type code %u",
213                      ty & MSG_CATMASK, ty & MSG_TYPEMASK);
214         break;
215     }
216   }
217
218   /* --- Fill in the tree --- */
219
220   if (t) {
221     ti = proto_tree_add_item(t, proto_tripe, b, 0, -1, FALSE);
222     tt = proto_item_add_subtree(ti, tt_tripe);
223
224     proto_tree_add_item(tt, hf_tripe_cat, b, 0, 1, FALSE);
225
226     off = 1;
227     switch (ty & MSG_CATMASK) {
228       case MSG_PACKET:
229         proto_tree_add_item(tt, hf_tripe_packet_type, b, 0, 1, FALSE);
230         switch (ty & MSG_TYPEMASK) {
231           case 0:
232             goto ct;
233           default:
234             goto huh;
235         }
236         break;
237       case MSG_KEYEXCH:
238         proto_tree_add_item(tt, hf_tripe_kx_type, b, 0, 1, FALSE);
239         switch (ty & MSG_TYPEMASK) {
240           case KX_PRECHAL:
241             off = getge(tt, &hf_tripe_kx_mychal, b, off);
242             goto tail;
243           case KX_CHAL:
244             off = getge(tt, &hf_tripe_kx_mychal, b, off);
245             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
246             off = getmp(tt, &hf_tripe_kx_check, b, off);
247             goto tail;
248           case KX_REPLY:
249             off = getge(tt, &hf_tripe_kx_mychal, b, off);
250             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
251             off = getmp(tt, &hf_tripe_kx_check, b, off);
252             goto ct;
253           case KX_SWITCH:
254             off = gethash(tt, hf_tripe_kx_mycookie, b, off);
255             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
256             goto ct;
257           case KX_SWITCHOK:
258             goto ct;
259           default:
260             goto huh;
261         }
262         break;
263       case MSG_MISC:
264         proto_tree_add_item(tt, hf_tripe_misc_type, b, 0, 1, FALSE);
265         switch (ty & MSG_TYPEMASK) {
266           case MISC_NOP:
267           case MISC_PING:
268           case MISC_PONG:
269           case MISC_GREET:
270             proto_tree_add_item(tt, hf_tripe_misc_payload,
271                                 b, off, -1, FALSE);
272             goto done;
273           case MISC_EPING:
274           case MISC_EPONG:
275             goto ct;
276           default:
277             goto huh;
278         }
279         break;
280       default:
281         goto huh;
282     }
283   tail:
284     if (tvb_offset_exists(b, off))
285       goto huh;
286     goto done;
287   huh:
288     proto_tree_add_item(tt, hf_tripe_huh, b, off, -1, FALSE);
289     goto done;
290   ct:
291     ti = proto_tree_add_item(tt, hf_tripe_ct, b, off, -1, FALSE);
292     seq = tvb_get_ntohl(b, off + tagsz);
293     proto_item_set_text(ti, "Encrypted ciphertext (sequence number %lu)",
294                         (unsigned long)seq);
295     tt = proto_item_add_subtree(ti, tt_tripe_ct);
296     if (tagsz) {
297       proto_tree_add_item(tt, hf_tripe_ct_tag, b, off, tagsz, FALSE);
298       off += tagsz;
299     }
300     proto_tree_add_item(tt, hf_tripe_ct_seq, b, off, 4, FALSE);
301     off += 4;
302     if (ivsz) {
303       proto_tree_add_item(tt, hf_tripe_ct_iv, b, off, ivsz, FALSE);
304       off += ivsz;
305     }
306     proto_tree_add_item(ti, hf_tripe_ct_ct, b, off, -1, FALSE);
307     goto done;
308   done:;
309   }
310 }
311
312 void proto_register_tripe(void)
313 {
314   module_t *mod;
315
316   static value_string vs_kxtype[] = {
317     { KX_PRECHAL,       "KX_PRECHAL (prechallenge)" },
318     { KX_CHAL,          "KX_CHAL (challenge)" },
319     { KX_REPLY,         "KX_REPLY (reply)" },
320     { KX_SWITCH,        "KX_SWITCH (switch request)" },
321     { KX_SWITCHOK,      "KX_SWITCHOK (switch response)" },
322     { 0,                0 }
323   };
324
325   static hf_register_info hfs[] = {
326     { &hf_tripe_cat, {
327       "Message category", "tripe.cat",
328       FT_UINT8, BASE_HEX, 0, MSG_CATMASK
329     } },
330     { &hf_tripe_packet_type, {
331       "Packet message type", "tripe.packet.type",
332       FT_UINT8, BASE_HEX, 0, MSG_TYPEMASK,
333       "This is the TrIPE packet type subcode."
334     } },
335     { &hf_tripe_ct, {
336       "Encrypted ciphertext", "tripe.ct",
337       FT_BYTES, BASE_NONE, 0, 0,
338       "This is an encrypted message."
339     } },
340     { &hf_tripe_ct_seq, {
341       "Ciphertext sequence number", "tripe.ct.seq",
342       FT_UINT32, BASE_DEC, 0, 0,
343       "This is the unique sequence number for the ciphertext."
344     } },
345     { &hf_tripe_ct_iv, {
346       "Ciphertext initialization vector", "tripe.ct.iv",
347       FT_BYTES, BASE_NONE, 0, 0,
348       "This is the initialization vector used for the actual encryption."
349     } },
350     { &hf_tripe_ct_ct, {
351       "Actual encrypted data", "tripe.ct.ct",
352       FT_BYTES, BASE_NONE, 0, 0,
353       "This is the encrypted message.  Reading it ought to be hard."
354     } },
355     { &hf_tripe_ct_tag, {
356       "Message authentication code", "tripe.ct.tag",
357       FT_BYTES, BASE_NONE, 0, 0,
358       "This is the message authentication code tag for the ciphertext."
359     } },
360     { &hf_tripe_misc_type, {
361       "Miscellaneous message type", "tripe.misc.type",
362       FT_UINT8, BASE_HEX, 0, MSG_TYPEMASK,
363       "This is the TrIPE miscellaneous message type subcode."
364     } },
365     { &hf_tripe_misc_payload, {
366       "Miscellaneous message payload", "tripe.misc.payload",
367       FT_BYTES, BASE_NONE, 0, 0,
368       "This is the miscellaneous message payload."
369     } },
370     { &hf_tripe_kx_type, {
371       "Key-exchange message type", "tripe.kx.type",
372       FT_UINT8, BASE_HEX, vs_kxtype, MSG_TYPEMASK,
373       "This is the TrIPE key-exchange type subcode."
374     } },
375     { &hf_tripe_kx_mychal.hf, {
376       "Sender's challenge data", "tripe.kx.mychal",
377       FT_BYTES, BASE_NONE, 0, 0,
378       "This is the sender's challenge."
379     } },
380     { &hf_tripe_kx_mychal.hf_len, {
381       "Challenge length", "tripe.kx.mychal.len",
382       FT_UINT16, BASE_DEC, 0, 0,
383       "This is the length of the sender's challenge."
384     } },
385     { &hf_tripe_kx_mychal.hf_val, {
386       "Challenge", "tripe.kx.mychal.val",
387       FT_BYTES, BASE_NONE, 0, 0,
388       "This is the value of the sender's challenge."
389     } },
390     { &hf_tripe_kx_mychal.hfx_len, {
391       "Challenge x length", "tripe.kx.mychal.x.len",
392       FT_UINT16, BASE_DEC, 0, 0,
393       "This is the length of the sender's challenge x-coordinate."
394     } },
395     { &hf_tripe_kx_mychal.hfx_val, {
396       "Challenge x value", "tripe.kx.mychal.x.val",
397       FT_BYTES, BASE_NONE, 0, 0,
398       "This is the value of the sender's challenge x-coordinate."
399     } },
400     { &hf_tripe_kx_mychal.hfy_len, {
401       "Challenge y length", "tripe.kx.mychal.y.len",
402       FT_UINT16, BASE_DEC, 0, 0,
403       "This is the length of the sender's challenge x-coordinate."
404     } },
405     { &hf_tripe_kx_mychal.hfy_val, {
406       "Challenge y value", "tripe.kx.mychal.y.val",
407       FT_BYTES, BASE_NONE, 0, 0,
408       "This is the value of the sender's challenge x-coordinate."
409     } },
410     { &hf_tripe_kx_mycookie, {
411       "Sender's hashed cookie", "tripe.kx.mycookie",
412       FT_BYTES, BASE_NONE, 0, 0,
413       "This is the hash of the sender's challenge."
414     } },
415     { &hf_tripe_kx_yourcookie, {
416       "Recipient's hashed cookie", "tripe.kx.yourcookie",
417       FT_BYTES, BASE_NONE, 0, 0,
418       "This is the hash of the recipient's challenge."
419     } },
420     { &hf_tripe_kx_check.hf, {
421       "Challenge check-value", "tripe.kx.check",
422       FT_BYTES, BASE_NONE, 0, 0,
423       "This is an encrypted check-value which proves that the sender "
424       "knows the answer to the challenge, and that it is therefore honest."
425     } },
426     { &hf_tripe_kx_check.hf_len, {
427       "Check-value length", "tripe.kx.check.len",
428       FT_UINT16, BASE_DEC, 0, 0,
429       "This is the length of the encrypted check-value."
430     } },
431     { &hf_tripe_kx_check.hf_val, {
432       "Check-value data", "tripe.kx.check.val",
433       FT_BYTES, BASE_NONE, 0, 0,
434       "This is the actual encrypted check-value."
435     } },
436     { &hf_tripe_huh, {
437       "Unknown data", "tripe.huh",
438       FT_BYTES, BASE_NONE, 0, 0,
439       "I don't know what's meant to appear here."
440     } },
441   };
442
443   static gint *tts[] = {
444     &tt_tripe,
445     &tt_tripe_ct,
446     &hf_tripe_kx_mychal.tt,
447     &hf_tripe_kx_check.tt,
448   };
449
450   proto_tripe = proto_register_protocol("TrIPE", "TrIPE", "tripe");
451   proto_register_field_array(proto_tripe, hfs, array_length(hfs));
452   proto_register_subtree_array(tts, array_length(tts));
453
454   mod = prefs_register_protocol(proto_tripe, prefcb);
455   prefs_register_uint_preference(mod, "hashsz", "Hash length",
456                                  "hash function output length (in octets)",
457                                  10, &hashsz);
458   prefs_register_uint_preference(mod, "tagsz", "MAC tag length",
459                                  "MAC tag length (in octets)", 10, &tagsz);
460   prefs_register_uint_preference(mod, "ivsz", "IV length",
461                                  "block cipher initialization vector length"
462                                  " (in octets)",
463                                  10, &ivsz);
464 }
465
466 void proto_reg_handoff_tripe(void)
467 {
468   dissector_handle_t dh;
469
470   dh = create_dissector_handle(dissect_tripe, proto_tripe);
471   dissector_add("udp.port", 22003, dh);
472 }
473
474 G_MODULE_EXPORT void plugin_reg_handoff(void)
475 {
476   proto_reg_handoff_tripe();
477 }
478
479 G_MODULE_EXPORT void plugin_register(void)
480 {
481   if (proto_tripe == -1)
482     proto_register_tripe();
483 }
484
485 /*----- That's all, folks -------------------------------------------------*/