chiark / gitweb /
Expunge revision histories in files.
[tripe] / ethereal / packet-tripe.c
1 /* -*-c-*-
2  *
3  * $Id: packet-tripe.c,v 1.3 2004/04/08 01:36:17 mdw Exp $
4  *
5  * TrIPE protocol dissector for Ethereal
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 <epan/packet.h>
42
43 #ifdef ETHEREAL_BUGGERED
44 #  define plugin_address_table_t void
45 #  define plugin_address_table_init(x)
46 #else
47 #  include <plugins/plugin_api.h>
48 #endif
49
50 #include "tripe-protocol.h"
51
52 /*----- Static variables --------------------------------------------------*/
53
54 static int proto_tripe = -1;
55
56 typedef struct hfmp {
57   int hf, hf_len, hf_val, tt;
58 } hfmp;
59 typedef struct hfge {
60   int hf, hf_len, hf_val, hfx_len, hfx_val, hfy_len, hfy_val, tt;
61 } hfge;
62
63 static int hf_tripe_cat = -1;
64 static int hf_tripe_packet_type = -1;
65 static int hf_tripe_ct = -1;
66 static int hf_tripe_ct_seq = -1;
67 static int hf_tripe_ct_iv = -1;
68 static int hf_tripe_ct_cbc = -1;
69 static int hf_tripe_ct_mac = -1;
70 static int hf_tripe_kx_type = -1;
71 static hfge hf_tripe_kx_mychal = { -1, -1, -1, -1, -1, -1, -1, -1 };
72 static int hf_tripe_kx_mycookie = -1;
73 static int hf_tripe_kx_yourcookie = -1;
74 static hfmp hf_tripe_kx_check = { -1, -1, -1, -1 };
75 static int hf_tripe_huh = -1;
76
77 static int tt_tripe = -1;
78 static int tt_tripe_ct = -1;
79
80 G_MODULE_EXPORT const gchar version[] = VERSION;
81
82 /*----- Main code ---------------------------------------------------------*/
83
84 static gint gethash(proto_tree *tt, int hf, tvbuff_t *b, gint off)
85 {
86   proto_tree_add_item(tt, hf, b, off, 20, FALSE);
87   return (off + 20); 
88 }
89
90 static gint getmp(proto_tree *tt, const hfmp *hf, tvbuff_t *b, gint off)
91 {
92   guint16 len = tvb_get_ntohs(b, off);
93   proto_item *ti = proto_tree_add_item(tt, hf->hf, b, off, len + 2, FALSE);
94   tt = proto_item_add_subtree(ti, hf->tt);
95   proto_tree_add_item(tt, hf->hf_len, b, off, 2, FALSE);
96   proto_tree_add_item(tt, hf->hf_val, b, off + 2, len, FALSE);
97   return (off + 2 + len);
98 }
99
100 static gint getge(proto_tree *tt, const hfge *hf, tvbuff_t *b, gint off)
101 {
102   guint16 len = tvb_get_ntohs(b, off), len2;
103   guint r;
104   proto_item *ti;
105   r = tvb_length_remaining(b, off);
106   if (r < 4 + len ||
107       (len2 = tvb_get_ntohs(b, off + 2 + len), r < 4 + len + len2)) {
108     ti = proto_tree_add_item(tt, hf->hf, b, off, len + 2, FALSE);
109     tt = proto_item_add_subtree(ti, hf->tt);
110     proto_tree_add_item(tt, hf->hf_len, b, off, 2, FALSE);
111     proto_tree_add_item(tt, hf->hf_val, b, off + 2, len, FALSE);
112     r = off + len + 2;
113   } else {
114     ti = proto_tree_add_item(tt, hf->hf, b, off, len + len2 + 4, FALSE);
115     tt = proto_item_add_subtree(ti, hf->tt);
116     proto_tree_add_item(tt, hf->hfx_len, b, off, 2, FALSE);
117     proto_tree_add_item(tt, hf->hfx_val, b, off + 2, len, FALSE);
118     proto_tree_add_item(tt, hf->hfy_len, b, off + 2 + len, 2, FALSE);
119     proto_tree_add_item(tt, hf->hfy_val, b, off + 4 + len, len2, FALSE);
120     r = off + len + len2 + 4;
121   }    
122   return (r);
123 }
124
125 static void dissect_tripe(tvbuff_t *b, packet_info *p, proto_tree *t)
126 {
127   proto_item *ti;
128   proto_tree *tt;
129   guint8 ty;
130   gint off = tvb_raw_offset(b);
131   guint32 seq;
132
133   /* --- Initialize the summary cells --- */
134
135   if (check_col(p->cinfo, COL_PROTOCOL))
136     col_set_str(p->cinfo, COL_PROTOCOL, "TrIPE");
137   ty = tvb_get_guint8(b, 0);
138   if (check_col(p->cinfo, COL_INFO)) {
139     col_clear(p->cinfo, COL_INFO);
140     switch (ty & MSG_CATMASK) {
141       case MSG_PACKET:
142         switch (ty & MSG_TYPEMASK) {
143           case 0:
144             col_set_str(p->cinfo, COL_INFO, "Packet data");
145             break;
146           default:
147             col_add_fstr(p->cinfo, COL_INFO,
148                          "Packet data, unknown type code %u",
149                          ty & MSG_TYPEMASK);
150             break;
151         }
152         break;
153       case MSG_KEYEXCH:
154         switch (ty & MSG_TYPEMASK) {
155           case KX_PRECHAL:
156             col_set_str(p->cinfo, COL_INFO, "Key exchange, prechallenge");
157             break;
158           case KX_COOKIE:
159             col_set_str(p->cinfo, COL_INFO, "Key exchange, cookie");
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       default:
181         col_add_fstr(p->cinfo, COL_INFO,
182                      "Unknown category code %u, unknown type code %u",
183                      ty & MSG_CATMASK, ty & MSG_TYPEMASK);
184         break;
185     }
186   }
187
188   /* --- Fill in the tree --- */
189
190   if (t) {
191     ti = proto_tree_add_item(t, proto_tripe, b, 0, -1, FALSE);
192     tt = proto_item_add_subtree(ti, tt_tripe);
193
194     proto_tree_add_item(tt, hf_tripe_cat, b, 0, 1, FALSE);
195
196     off = 1;
197     switch (ty & MSG_CATMASK) {
198       case MSG_PACKET:
199         proto_tree_add_item(tt, hf_tripe_packet_type, b, 0, 1, FALSE);
200         switch (ty & MSG_TYPEMASK) {
201           case 0:
202             goto ct;
203           default:
204             goto huh;
205         }
206         break;
207       case MSG_KEYEXCH:
208         proto_tree_add_item(tt, hf_tripe_kx_type, b, 0, 1, FALSE);
209         switch (ty & MSG_TYPEMASK) {
210           case KX_PRECHAL:
211             off = getge(tt, &hf_tripe_kx_mychal, b, off);
212             goto tail;
213           case KX_COOKIE:
214             off = getge(tt, &hf_tripe_kx_mychal, b, off);
215             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
216             goto tail;
217           case KX_CHAL:
218             off = getge(tt, &hf_tripe_kx_mychal, b, off);
219             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
220             off = getmp(tt, &hf_tripe_kx_check, b, off);
221             goto tail;
222           case KX_REPLY:
223             off = gethash(tt, hf_tripe_kx_mycookie, b, off);
224             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
225             off = getmp(tt, &hf_tripe_kx_check, b, off);
226             goto ct;
227           case KX_SWITCH:
228             off = gethash(tt, hf_tripe_kx_mycookie, b, off);
229             off = gethash(tt, hf_tripe_kx_yourcookie, b, off);
230             goto ct;
231           case KX_SWITCHOK:
232             goto ct;
233           default:
234             goto huh;
235         }
236         break;
237       default:
238         goto huh;
239     }
240   tail:
241     if (tvb_offset_exists(b, off))
242       goto huh;
243     goto done;
244   huh:
245     proto_tree_add_item(tt, hf_tripe_huh, b, off, -1, FALSE);
246     goto done;
247   ct:
248     ti = proto_tree_add_item(tt, hf_tripe_ct, b, off, -1, FALSE);
249     seq = tvb_get_ntohl(b, off + 10);
250     proto_item_set_text(ti, "Encrypted ciphertext (sequence number %lu)",
251                         (unsigned long)seq);
252     tt = proto_item_add_subtree(ti, tt_tripe_ct);
253     proto_tree_add_item(tt, hf_tripe_ct_mac, b, off, 10, FALSE);
254     off += 10;
255     proto_tree_add_item(tt, hf_tripe_ct_seq, b, off, 4, FALSE);
256     off += 4;
257     proto_tree_add_item(tt, hf_tripe_ct_iv, b, off, 8, FALSE);
258     off += 8;
259     proto_tree_add_item(ti, hf_tripe_ct_cbc, b, off, -1, FALSE);
260     goto done;
261   done:;
262   }  
263 }
264
265 void proto_register_tripe(void)
266 {
267   static value_string vs_kxtype[] = {
268     { KX_PRECHAL,       "KX_PRECHAL (prechallenge)" },
269     { KX_COOKIE,        "KX_COOKIE (cookie)" },
270     { KX_CHAL,          "KX_CHAL (challenge)" },
271     { KX_REPLY,         "KX_REPLY (reply)" },
272     { KX_SWITCH,        "KX_SWITCH (switch request)" },
273     { KX_SWITCHOK,      "KX_SWITCHOK (switch response)" },
274     { 0,                0 }
275   };
276
277   static hf_register_info hfs[] = {
278     &hf_tripe_cat, {
279       "Message category", "tripe.cat",
280       FT_UINT8, BASE_HEX, 0, MSG_CATMASK
281     },
282     &hf_tripe_packet_type, {
283       "Packet message type", "tripe.packet.type",
284       FT_UINT8, BASE_HEX, 0, MSG_TYPEMASK,
285       "This is the TrIPE packet type subcode."
286     },
287     &hf_tripe_ct, {
288       "Encrypted ciphertext", "tripe.ct",
289       FT_BYTES, BASE_NONE, 0, 0,
290       "This is an encrypted message."
291     },
292     &hf_tripe_ct_seq, {
293       "Ciphertext sequence number", "tripe.ct.seq",
294       FT_UINT32, BASE_DEC, 0, 0,
295       "This is the unique sequence number for the ciphertext."
296     },
297     &hf_tripe_ct_iv, {
298       "Ciphertext initialization vector", "tripe.ct.iv",
299       FT_BYTES, BASE_NONE, 0, 0,
300       "This is the initialization vector used for the actual encryption."
301     },
302     &hf_tripe_ct_cbc, {
303       "CBC-encrypted data", "tripe.ct.cbc",
304       FT_BYTES, BASE_NONE, 0, 0,
305       "This is the CBC-encrypted message.  Reading it ought to be hard."
306     },
307     &hf_tripe_ct_mac, {
308       "Message authentication code", "tripe.ct.mac",
309       FT_BYTES, BASE_NONE, 0, 0,
310       "This is the message authentication code for the ciphertext."
311     },
312     &hf_tripe_kx_type, {
313       "Key-exchange message type", "tripe.kx.type",
314       FT_UINT8, BASE_HEX, vs_kxtype, MSG_TYPEMASK,
315       "This is the TrIPE key-exchange type subcode."
316     },
317     &hf_tripe_kx_mychal.hf, {
318       "Sender's challenge data", "tripe.kx.mychal",
319       FT_BYTES, BASE_NONE, 0, 0,
320       "This is the sender's challenge."
321     },
322     &hf_tripe_kx_mychal.hf_len, {
323       "Challenge length", "tripe.kx.mychal.len",
324       FT_UINT16, BASE_DEC, 0, 0,
325       "This is the length of the sender's challenge."
326     },
327     &hf_tripe_kx_mychal.hf_val, {
328       "Challenge", "tripe.kx.mychal.val",
329       FT_BYTES, BASE_NONE, 0, 0,
330       "This is the value of the sender's challenge."
331     },
332     &hf_tripe_kx_mychal.hfx_len, {
333       "Challenge x length", "tripe.kx.mychal.x.len",
334       FT_UINT16, BASE_DEC, 0, 0,
335       "This is the length of the sender's challenge x-coordinate."
336     },
337     &hf_tripe_kx_mychal.hfy_val, {
338       "Challenge x value", "tripe.kx.mychal.x.val",
339       FT_BYTES, BASE_NONE, 0, 0,
340       "This is the value of the sender's challenge x-coordinate."
341     },
342     &hf_tripe_kx_mychal.hfy_len, {
343       "Challenge y length", "tripe.kx.mychal.y.len",
344       FT_UINT16, BASE_DEC, 0, 0,
345       "This is the length of the sender's challenge x-coordinate."
346     },
347     &hf_tripe_kx_mychal.hfx_val, {
348       "Challenge y value", "tripe.kx.mychal.y.val",
349       FT_BYTES, BASE_NONE, 0, 0,
350       "This is the value of the sender's challenge x-coordinate."
351     },
352     &hf_tripe_kx_mycookie, {
353       "Sender's hashed cookie", "tripe.kx.mycookie",
354       FT_BYTES, BASE_NONE, 0, 0,
355       "This is the hash of the sender's challenge."
356     },
357     &hf_tripe_kx_yourcookie, {
358       "Recipient's hashed cookie", "tripe.kx.yourcookie",
359       FT_BYTES, BASE_NONE, 0, 0,
360       "This is the hash of the recipient's challenge."
361     },
362     &hf_tripe_kx_check.hf, {
363       "Challenge check-value", "tripe.kx.check",
364       FT_BYTES, BASE_NONE, 0, 0,
365       "This is an encrypted check-value which proves that the sender "
366       "knows the answer to the challenge, and that it is therefore honest."
367     },
368     &hf_tripe_kx_check.hf_len, {
369       "Check-value length", "tripe.kx.check.len",
370       FT_UINT16, BASE_DEC, 0, 0,
371       "This is the length of the encrypted check-value."
372     },
373     &hf_tripe_kx_check.hf_val, {
374       "Check-value data", "tripe.kx.check.val",
375       FT_BYTES, BASE_NONE, 0, 0,
376       "This is the actual encrypted check-value."
377     },
378     &hf_tripe_huh, {
379       "Unknown data", "tripe.huh",
380       FT_BYTES, BASE_NONE, 0, 0,
381       "I don't know what's meant to appear here."
382     },
383   };
384
385   static gint *tts[] = {
386     &tt_tripe,
387     &tt_tripe_ct,
388     &hf_tripe_kx_mychal.tt,
389     &hf_tripe_kx_check.tt,
390   };
391
392   proto_tripe = proto_register_protocol("TrIPE", "TrIPE", "tripe");
393   proto_register_field_array(proto_tripe, hfs, array_length(hfs));
394   proto_register_subtree_array(tts, array_length(tts));
395 }
396
397 void proto_reg_handoff_tripe(void)
398 {
399   dissector_handle_t dh;
400
401   dh = create_dissector_handle(dissect_tripe, proto_tripe);
402   dissector_add("udp.port", 22003, dh);
403 }
404
405 G_MODULE_EXPORT void plugin_reg_handoff(void)
406 {
407   proto_reg_handoff_tripe();
408 }
409
410 G_MODULE_EXPORT void plugin_init(plugin_address_table_t *pat)
411 {
412   plugin_address_table_init(pat);
413   if (proto_tripe == -1)
414     proto_register_tripe();
415 }
416
417 /*----- That's all, folks -------------------------------------------------*/