UATs could be put into "categories". The categories were defined only
[metze/wireshark/wip.git] / epan / dissectors / packet-c1222.c
1 /* Do not modify this file.                                                   */
2 /* It is created automatically by the ASN.1 to Wireshark dissector compiler   */
3 /* packet-c1222.c                                                             */
4 /* ../../tools/asn2wrs.py -b -p c1222 -c ./c1222.cnf -s ./packet-c1222-template -D . -O ../../epan/dissectors c1222.asn */
5
6 /* Input file: packet-c1222-template.c */
7
8 #line 1 "../../asn1/c1222/packet-c1222-template.c"
9 /* packet-c1222.c
10  * Routines for ANSI C12.22 packet dissection
11  * Copyright 2010, Edward J. Beroset, edward.j.beroset@us.elster.com
12  *
13  * $Id$
14  *
15  * Wireshark - Network traffic analyzer
16  * By Gerald Combs <gerald@wireshark.org>
17  * Copyright 1998 Gerald Combs
18  *
19  * This program is free software; you can redistribute it and/or
20  * modify it under the terms of the GNU General Public License
21  * as published by the Free Software Foundation; either version 2
22  * of the License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32  */
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <glib.h>
39 #include <epan/conversation.h>
40 #include <wsutil/crc16.h>
41 #include <epan/expert.h>
42 #include <epan/packet.h>
43 #include <epan/prefs.h>
44 #include <epan/strutil.h>
45 #include <epan/dissectors/packet-ber.h>
46 #include <epan/dissectors/packet-tcp.h>
47 #include <epan/uat.h>
48 #include <epan/crypt/eax.h>
49
50 #include <stdio.h>
51 #include <string.h>
52
53 #include "packet-c1222.h"
54
55 #define PNAME  "ANSI C12.22"
56 #define PSNAME "C12.22"
57 #define PFNAME "c1222"
58 #define C1222_PORT 1153    /* TCP port */
59
60 /* C12.22 flag definitions */
61 #define C1222_EPSEM_FLAG_RESERVED 0x80
62 #define C1222_EPSEM_FLAG_RECOVERY_SESSION 0x40
63 #define C1222_EPSEM_FLAG_PROXY_SERVICE_USED 0x20
64 #define C1222_EPSEM_FLAG_ED_CLASS_INCLUDED 0x10
65 #define C1222_EPSEM_FLAG_SECURITY_MODE 0x0c
66 #define C1222_EPSEM_FLAG_RESPONSE_CONTROL 0x03
67
68 /* if the packet is encrypted, it can be
69  * good, bad, or simply not checked
70  */
71 #define C1222_EPSEM_CRYPTO_GOOD 0x01
72 #define C1222_EPSEM_CRYPTO_BAD 0x02
73
74 /* these defines are for each of the C12.22 services */
75 #define C1222_CMD_IDENTIFY 0x20
76 #define C1222_CMD_TERMINATE 0x21
77 #define C1222_CMD_DISCONNECT 0x22
78 #define C1222_CMD_FULL_READ 0x30
79 #define C1222_CMD_DEFAULT_READ 0x3E
80 #define C1222_CMD_PARTIAL_READ_OFFSET 0x3F
81 #define C1222_CMD_FULL_WRITE 0x40
82 #define C1222_CMD_DEFAULT_WRITE 0x4E
83 #define C1222_CMD_PARTIAL_WRITE_OFFSET 0x4F
84 #define C1222_CMD_LOGON 0x50
85 #define C1222_CMD_SECURITY 0x51
86 #define C1222_CMD_LOGOFF 0x52
87 #define C1222_CMD_AUTHENTICATE 0x53
88 #define C1222_CMD_NEGOTIATE 0x60
89 #define C1222_CMD_WAIT 0x70
90 #define C1222_CMD_TIMING_SETUP 0x71
91
92 static dissector_handle_t c1222_handle=NULL;
93
94 /* Initialize the protocol and registered fields */
95 static int proto_c1222 = -1;
96 static int global_c1222_port = C1222_PORT;
97 static gboolean c1222_desegment = TRUE;
98 static gboolean c1222_decrypt = TRUE;
99
100
101 /*--- Included file: packet-c1222-hf.c ---*/
102 #line 1 "../../asn1/c1222/packet-c1222-hf.c"
103 static int hf_c1222_C1222_MESSAGE_PDU = -1;       /* C1222_MESSAGE */
104 static int hf_c1222_aSO_context = -1;             /* ASO_qualifier */
105 static int hf_c1222_called_AP_title = -1;         /* Called_AP_title */
106 static int hf_c1222_called_AP_invocation_id = -1;  /* Called_AP_invocation_id */
107 static int hf_c1222_calling_AP_title = -1;        /* Calling_AP_title */
108 static int hf_c1222_calling_AE_qualifier = -1;    /* Calling_AE_qualifier */
109 static int hf_c1222_calling_AP_invocation_id = -1;  /* Calling_AP_invocation_id */
110 static int hf_c1222_mechanism_name = -1;          /* Mechanism_name */
111 static int hf_c1222_calling_authentication_value = -1;  /* Calling_authentication_value */
112 static int hf_c1222_user_information = -1;        /* User_information */
113 static int hf_c1222_calling_authentication_value_indirect = -1;  /* INTEGER */
114 static int hf_c1222_calling_authentication_value_encoding = -1;  /* Authentication_value_encoding */
115 static int hf_c1222_calling_authentication_value_single_asn1 = -1;  /* Calling_authentication_value_single_asn1 */
116 static int hf_c1222_calling_authentication_value_octet_aligned = -1;  /* OCTET_STRING */
117 static int hf_c1222_calling_authentication_value_c1222 = -1;  /* Calling_authentication_value_c1222 */
118 static int hf_c1222_calling_authentication_value_c1221 = -1;  /* Calling_authentication_value_c1221 */
119 static int hf_c1222_key_id_element = -1;          /* Key_id_element */
120 static int hf_c1222_iv_element = -1;              /* Iv_element */
121 static int hf_c1222_c1221_auth_identification = -1;  /* OCTET_STRING_SIZE_CONSTR001 */
122 static int hf_c1222_c1221_auth_request = -1;      /* OCTET_STRING_SIZE_1_255 */
123 static int hf_c1222_c1221_auth_response = -1;     /* OCTET_STRING_SIZE_CONSTR002 */
124
125 /*--- End of included file: packet-c1222-hf.c ---*/
126 #line 93 "../../asn1/c1222/packet-c1222-template.c"
127 /* These are the EPSEM pieces */
128 /* first, the flag components */
129 static int hf_c1222_epsem_flags = -1;
130 static int hf_c1222_epsem_flags_reserved = -1;
131 static int hf_c1222_epsem_flags_recovery = -1;
132 static int hf_c1222_epsem_flags_proxy = -1;
133 static int hf_c1222_epsem_flags_ed_class = -1;
134 static int hf_c1222_epsem_flags_security_modes = -1;
135 static int hf_c1222_epsem_flags_response_control = -1;
136 /* and the structure of the flag components */
137 static const int *c1222_flags[] = {
138   &hf_c1222_epsem_flags_reserved,
139   &hf_c1222_epsem_flags_recovery,
140   &hf_c1222_epsem_flags_proxy,
141   &hf_c1222_epsem_flags_ed_class,
142   &hf_c1222_epsem_flags_security_modes,
143   &hf_c1222_epsem_flags_response_control,
144   NULL
145 };
146 /* next the optional ed_class */
147 static int hf_c1222_epsem_ed_class = -1;
148 /* now the aggregate epsem */
149 static int hf_c1222_epsem_total = -1;
150 /* generic command */
151 static int hf_c1222_cmd = -1;
152 static int hf_c1222_err = -1;
153 static int hf_c1222_data = -1;
154 static int hf_c1222_crc = -1;
155 /* individual epsem fields */
156 static int hf_c1222_logon_id = -1;
157 static int hf_c1222_logon_user = -1;
158 static int hf_c1222_security_password = -1;
159 static int hf_c1222_auth_len = -1;
160 static int hf_c1222_auth_data = -1;
161 static int hf_c1222_read_table = -1;
162 static int hf_c1222_read_offset = -1;
163 static int hf_c1222_read_count = -1;
164 static int hf_c1222_write_table = -1;
165 static int hf_c1222_write_offset = -1;
166 static int hf_c1222_write_size = -1;
167 static int hf_c1222_write_data = -1;
168 static int hf_c1222_write_chksum = -1;
169 static int hf_c1222_wait_secs = -1;
170 static int hf_c1222_neg_pkt_size = -1;
171 static int hf_c1222_neg_nbr_pkts = -1;
172 static int hf_c1222_timing_setup_traffic = -1;
173 static int hf_c1222_timing_setup_inter_char = -1;
174 static int hf_c1222_timing_setup_resp_to = -1;
175 static int hf_c1222_timing_setup_nbr_retries = -1;
176
177 /* the MAC */
178 static int hf_c1222_epsem_mac = -1;
179
180 /* crypto result flags */
181 static int hf_c1222_epsem_crypto_good = -1;
182 static int hf_c1222_epsem_crypto_bad = -1;
183
184 /* Initialize the subtree pointers */
185 static int ett_c1222 = -1;
186 static int ett_c1222_epsem = -1;
187 static int ett_c1222_flags = -1;
188 static int ett_c1222_crypto = -1;
189 static int ett_c1222_cmd = -1;
190
191 #ifdef HAVE_LIBGCRYPT
192 /* these pointers are for the header elements that may be needed to verify the crypto */
193 static guint8 *aSO_context = NULL;
194 static guint8 *called_AP_title = NULL;
195 static guint8 *called_AP_invocation_id = NULL;
196 static guint8 *calling_AE_qualifier = NULL;
197 static guint8 *calling_AP_invocation_id = NULL;
198 static guint8 *mechanism_name = NULL;
199 static guint8 *calling_authentication_value = NULL;
200 static guint8 *user_information = NULL;
201 static guint8 *calling_AP_title = NULL;
202 static guint8 *key_id_element = NULL;
203 static guint8 *iv_element = NULL;
204
205 /* these are the related lengths */
206 static guint32 aSO_context_len = 0;
207 static guint32 called_AP_title_len = 0;
208 static guint32 called_AP_invocation_id_len = 0;
209 static guint32 calling_AE_qualifier_len = 0;
210 static guint32 calling_AP_invocation_id_len = 0;
211 static guint32 mechanism_name_len = 0;
212 static guint32 calling_authentication_value_len = 0;
213 static guint32 user_information_len = 0;
214 static guint32 calling_AP_title_len = 0;
215 static guint32 key_id_element_len = 0;
216 static guint32 iv_element_len = 0;
217 #endif /* HAVE_LIBGCRYPT */
218
219
220 /*--- Included file: packet-c1222-ett.c ---*/
221 #line 1 "../../asn1/c1222/packet-c1222-ett.c"
222 static gint ett_c1222_C1222_MESSAGE_U = -1;
223 static gint ett_c1222_Calling_authentication_value_U = -1;
224 static gint ett_c1222_Authentication_value_encoding = -1;
225 static gint ett_c1222_Calling_authentication_value_single_asn1 = -1;
226 static gint ett_c1222_Calling_authentication_value_c1222_U = -1;
227 static gint ett_c1222_Calling_authentication_value_c1221_U = -1;
228
229 /*--- End of included file: packet-c1222-ett.c ---*/
230 #line 186 "../../asn1/c1222/packet-c1222-template.c"
231
232
233 /*------------------------------
234  * Data Structures 
235  *------------------------------
236  */
237 typedef struct _c1222_uat_data {
238   guint keynum;
239   guchar *key;
240   guint  keylen;
241 } c1222_uat_data_t;
242
243 static const value_string c1222_security_modes[] = {
244   { 0x00, "Cleartext"}, 
245   { 0x01, "Cleartext with authentication"}, 
246   { 0x02, "Ciphertext with authentication"}, 
247   { 0, NULL }
248 };
249
250 static const value_string c1222_response_control[] = {
251   { 0x00, "Always respond"}, 
252   { 0x01, "Respond on exception"}, 
253   { 0x02, "Never respond"}, 
254   { 0, NULL }
255 };
256
257 static const value_string tableflags[] = {
258   { 0x00, "ST" },
259   { 0x08, "MT" },
260   { 0x10, "Pending ST" },
261   { 0x18, "Pending MT" },
262   { 0, NULL }
263 };
264
265 static const value_string procflags[] = {
266   { 0x00, "SF" },
267   { 0x01, "MF" },
268   { 0, NULL }
269 };
270
271 static const value_string commandnames[] = {
272 /* error codes are in the range 0x00 - 0x1f inclusive */
273   { 0x00, "OK" },
274   { 0x01, "Error" },
275   { 0x02, "Service Not Supported" },
276   { 0x03, "Insufficient Security Clearance" },
277   { 0x04, "Operation Not Possible" },
278   { 0x05, "Inappropriate Action Requested" },
279   { 0x06, "Device Busy" },
280   { 0x07, "Data Not Ready" },
281   { 0x08, "Data Locked" },
282   { 0x09, "Renegotiate Request" },
283   { 0x0A, "Invalid Service Sequence State" },
284   { 0x0B, "Security Mechanism Error" },
285   { 0x0C, "Unknown Application Title" },
286   { 0x0D, "Network Time-out" },
287   { 0x0E, "Network Not Reachable" },
288   { 0x0F, "Request Too Large" },
289   { 0x10, "Response Too Large" },
290   { 0x11, "Segmentation Not Possible" },
291   { 0x12, "Segmentation Error" },
292 /* commands are in the range 0x20 - 0x7f inclusive */
293   {C1222_CMD_IDENTIFY, "Identify" },
294   {C1222_CMD_TERMINATE, "Terminate" },
295   {C1222_CMD_DISCONNECT, "Disconnect" },
296   {C1222_CMD_FULL_READ, "Full Read" },
297   {C1222_CMD_DEFAULT_READ, "Default Read" },
298   {C1222_CMD_PARTIAL_READ_OFFSET, "Partial Read Offset" },
299   {C1222_CMD_FULL_WRITE, "Full Write" },
300   {C1222_CMD_DEFAULT_WRITE, "Default Write" },
301   {C1222_CMD_PARTIAL_WRITE_OFFSET, "Partial Write Offset" },
302   {C1222_CMD_LOGON, "Logon" },
303   {C1222_CMD_SECURITY, "Security" },
304   {C1222_CMD_LOGOFF, "Logoff" },
305   {C1222_CMD_AUTHENTICATE, "Authenticate" },
306   {C1222_CMD_NEGOTIATE, "Negotiate" },
307   {C1222_CMD_NEGOTIATE | 0x1, "Negotiate w/ 1 Baud Rate" },
308   {C1222_CMD_NEGOTIATE | 0x2, "Negotiate w/ 2 Baud Rates" },
309   {C1222_CMD_NEGOTIATE | 0x3, "Negotiate w/ 3 Baud Rates" },
310   {C1222_CMD_NEGOTIATE | 0x4, "Negotiate w/ 4 Baud Rates" },
311   {C1222_CMD_NEGOTIATE | 0x5, "Negotiate w/ 5 Baud Rates" },
312   {C1222_CMD_NEGOTIATE | 0x6, "Negotiate w/ 6 Baud Rates" },
313   {C1222_CMD_NEGOTIATE | 0x7, "Negotiate w/ 7 Baud Rates" },
314   {C1222_CMD_NEGOTIATE | 0x8, "Negotiate w/ 8 Baud Rates" },
315   {C1222_CMD_NEGOTIATE | 0x9, "Negotiate w/ 9 Baud Rates" },
316   {C1222_CMD_NEGOTIATE | 0xA, "Negotiate w/ 10 Baud Rates" },
317   {C1222_CMD_NEGOTIATE | 0xB, "Negotiate w/ 11 Baud Rates" },
318   {C1222_CMD_WAIT, "Wait" },
319   {C1222_CMD_TIMING_SETUP, "Timing Setup" },
320   { 0, NULL }
321 };
322
323 #ifdef HAVE_LIBGCRYPT
324 /* these are for the key tables */
325 UAT_HEX_CB_DEF(c1222_users, keynum, c1222_uat_data_t)
326 UAT_BUFFER_CB_DEF(c1222_users, key, c1222_uat_data_t, key, keylen)
327
328 static c1222_uat_data_t *c1222_uat_data = NULL;
329 static guint num_c1222_uat_data = 0;
330 static uat_t *c1222_uat;
331
332 /* these macros ares used to populate fields needed to verify crypto */
333 #define FILL_START int length, start_offset = offset; 
334 #define FILL_TABLE(fieldname)  \
335   length = offset - start_offset; \
336   fieldname = tvb_memdup(tvb, start_offset, length); \
337   fieldname##_len = length; 
338 #define FILL_TABLE_TRUNCATE(fieldname, len)  \
339   length = 1 + 2*(offset - start_offset); \
340   fieldname = tvb_memdup(tvb, start_offset, length); \
341   fieldname##_len = len; 
342 #else /* HAVE_LIBGCRYPT */
343 #define FILL_TABLE(fieldname) 
344 #define FILL_TABLE_TRUNCATE(fieldname, len)  
345 #define FILL_START
346 #endif /* HAVE_LIBGCRYPT */
347
348 /*------------------------------
349  * Function Prototypes 
350  *------------------------------
351  */
352 void proto_reg_handoff_c1222(void);
353
354
355 /*------------------------------
356  * Code 
357  *------------------------------
358  */
359
360 /**
361  * Calculates simple one's complement checksum.
362  *
363  * \param tvb pointer to tvbuff containing data to be checksummed 
364  * \param offset offset within tvbuff to beginning of data
365  * \param len length of data to be checksummed
366  * \returns calculated checksum
367  */
368 static guint8
369 c1222_cksum(tvbuff_t *tvb, gint offset, int len)
370 {
371   guint8 sum;
372   for (sum = 0; len; offset++, len--)
373     sum += tvb_get_guint8(tvb, offset);
374   return ~sum + 1;
375 }
376 /**
377  * Dissects C12.22 packet in detail (with a tree).
378  *
379  * \param tvb input buffer containing packet to be dissected
380  * \param pinfo
381  * \param tree
382  * \param length
383  * \param offset
384  */
385 static void
386 parse_c1222_detailed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int cmd, guint32 *length, int *offset)
387 {
388   guint16 user_id = 0;
389   guint8 *user_name = NULL;
390   guint8 *password = NULL;
391   guint8 auth_len = 0;
392   gchar *auth_req = NULL;
393   guint16 table = 0;
394   guint16 tblsize = 0;
395   guint8 chksum = 0;
396   guint16 calcsum = 0;
397   guint8 wait_seconds = 0;
398   int numrates = 0;
399   guint16 packet_size;
400   guint8 nbr_packet;
401   /* timing setup parameters */
402   guint8 traffic; 
403   guint8 inter_char; 
404   guint8 resp_to; 
405   guint8 nbr_retries;
406   proto_item *item = NULL;
407
408   /* special case to simplify handling of Negotiate service */
409   if ((cmd & 0xF0) == C1222_CMD_NEGOTIATE) {
410     numrates = cmd & 0x0F;
411     cmd = C1222_CMD_NEGOTIATE;
412   }
413   proto_tree_add_uint(tree, cmd >= 0x20 ? hf_c1222_cmd : hf_c1222_err, tvb, *offset, 1, cmd);
414   (*offset)++;
415   (*length)--;
416   switch (cmd) {
417     case C1222_CMD_LOGON:
418         if (*length >= 12) {
419             user_id = tvb_get_ntohs(tvb, *offset);
420             proto_tree_add_uint(tree, hf_c1222_logon_id, tvb, *offset, 2, user_id);
421             *offset += 2;
422             user_name = tvb_get_ephemeral_string(tvb, *offset, 10);
423             proto_tree_add_string(tree, hf_c1222_logon_user, tvb, *offset, 10, user_name);
424             *offset += 10;
425             *length -= 12;
426             proto_item_set_text(tree, "C12.22 EPSEM: %s (id %d, user \"%s\")", 
427                     val_to_str(cmd,commandnames,"Unknown (0x%02x)"), user_id, user_name);
428         } else {
429             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 LOGON command truncated");
430         }
431         break;
432     case C1222_CMD_SECURITY:
433         if (*length >= 20) {
434             password = tvb_get_ephemeral_string(tvb, *offset, 20);
435             proto_tree_add_string(tree, hf_c1222_security_password, tvb, *offset, 20, password);
436             *offset += 20;
437             *length -= 20;
438             if (*length >= 2) {
439               user_id = tvb_get_ntohs(tvb, *offset);
440               proto_tree_add_uint(tree, hf_c1222_logon_id, tvb, *offset, 2, user_id);
441               *offset += 2;
442               *length -= 2;
443               proto_item_set_text(tree, "C12.22 EPSEM: %s (password \"%s\", id %d)",
444                       val_to_str(cmd,commandnames,"Unknown (0x%02x)"), password, user_id);
445             } else {
446               proto_item_set_text(tree, "C12.22 EPSEM: %s (password \"%s\")",
447                       val_to_str(cmd,commandnames,"Unknown (0x%02x)"), password);
448             }
449         } else {
450             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 SECURITY command truncated");
451         }
452         break;
453     case C1222_CMD_AUTHENTICATE:
454         if (*length >= 1) {
455             auth_len = tvb_get_guint8(tvb, *offset);
456             proto_tree_add_uint(tree, hf_c1222_auth_len, tvb, *offset, 1, auth_len);
457             *offset += 1;
458             if (*length >= auth_len) {
459                 auth_req = tvb_bytes_to_str(tvb, *offset, auth_len);
460                 proto_tree_add_item(tree, hf_c1222_auth_data, tvb, *offset, auth_len, ENC_NA);
461                 *offset += auth_len;
462                 *length -= auth_len + 1;
463                 proto_item_set_text(tree, "C12.22 EPSEM: %s (%d bytes: %s)", 
464                     val_to_str(cmd,commandnames,"Unknown (0x%02x)"), auth_len, auth_req);
465             } else {
466                 expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 AUTHENTICATE command truncated");
467             }
468         } else {
469             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 AUTHENTICATE command truncated");
470         }
471         break;
472     case C1222_CMD_FULL_READ:
473         if (*length >= 2) {
474             table = tvb_get_ntohs(tvb, *offset);
475             proto_tree_add_uint(tree, hf_c1222_read_table, tvb, *offset, 2, table);
476             proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
477                     val_to_str(cmd,commandnames,"Unknown (0x%02x)"), 
478                     val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
479             *offset += 2;
480             *length -= 2;
481         } else {
482             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 READ command truncated");
483         }
484         break;
485     case C1222_CMD_PARTIAL_READ_OFFSET:
486         if (*length >= 7) {
487             table = tvb_get_ntohs(tvb, *offset);
488             proto_tree_add_uint(tree, hf_c1222_read_table, tvb, *offset, 2, table);
489             *offset += 2;
490             *length -= 2;
491             proto_tree_add_item(tree, hf_c1222_read_offset, tvb, *offset, 3, ENC_BIG_ENDIAN);
492             *offset += 3;
493             *length -= 3;
494             proto_tree_add_item(tree, hf_c1222_read_count, tvb, *offset, 2, ENC_BIG_ENDIAN);
495             *offset += 2;
496             *length -= 2;
497             proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
498                     val_to_str(cmd,commandnames,"Unknown (0x%02x)"), 
499                     val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
500         } else {
501             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 READ command truncated");
502         }
503         break;
504     case C1222_CMD_FULL_WRITE:
505         if (*length >= 5) {
506             table = tvb_get_ntohs(tvb, *offset);
507             proto_tree_add_uint(tree, hf_c1222_write_table, tvb, *offset, 2, table);
508             *offset += 2;
509             *length -= 2;
510             tblsize = tvb_get_ntohs(tvb, *offset);
511             proto_tree_add_uint(tree, hf_c1222_write_size, tvb, *offset, 2, tblsize);
512             *offset += 2;
513             *length -= 2;
514             if (*length >= tblsize+1U) {
515                 proto_tree_add_item(tree, hf_c1222_write_data, tvb, *offset, tblsize, ENC_NA);
516                 *offset += tblsize;
517                 *length -= tblsize;
518                 chksum = tvb_get_guint8(tvb, *offset);
519                 item = proto_tree_add_uint(tree, hf_c1222_write_chksum, tvb, *offset, 1, chksum);
520                 calcsum = c1222_cksum(tvb, (*offset)-tblsize, tblsize);
521                 if (chksum != calcsum) {
522                   expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum [should be 0x%02x]", calcsum);
523                 }
524                 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
525                         val_to_str(cmd,commandnames,"Unknown (0x%02x)"), 
526                         val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
527                 *offset += 1;
528                 *length -= 1;
529             } else {
530                 expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 WRITE command truncated");
531             }
532         } else {
533             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 WRITE command truncated");
534         }
535         break;
536     case C1222_CMD_PARTIAL_WRITE_OFFSET:
537         if (*length >= 8) {
538             table = tvb_get_ntohs(tvb, *offset);
539             proto_tree_add_uint(tree, hf_c1222_write_table, tvb, *offset, 2, table);
540             *offset += 2;
541             *length -= 2;
542             proto_tree_add_item(tree, hf_c1222_write_offset, tvb, *offset, 3, ENC_BIG_ENDIAN);
543             *offset += 3;
544             *length -= 3;
545             tblsize = tvb_get_ntohs(tvb, *offset);
546             proto_tree_add_uint(tree, hf_c1222_write_size, tvb, *offset, 2, tblsize);
547             *offset += 2;
548             *length -= 2;
549             if (*length >= tblsize+1U) {
550                 proto_tree_add_item(tree, hf_c1222_write_data, tvb, *offset, tblsize, ENC_NA);
551                 *offset += tblsize;
552                 *length -= tblsize;
553                 chksum = tvb_get_guint8(tvb, *offset);
554                 item = proto_tree_add_uint(tree, hf_c1222_write_chksum, tvb, *offset, 1, chksum);
555                 calcsum = c1222_cksum(tvb, (*offset)-tblsize, tblsize);
556                 if (chksum != calcsum) {
557                   expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum [should be 0x%02x]", calcsum);
558                 }
559                 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
560                         val_to_str(cmd,commandnames,"Unknown (0x%02x)"), 
561                         val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
562                 *offset += 1;
563                 *length -= 1;
564             } else {
565                 expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 WRITE command truncated");
566             }
567         } else {
568             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 WRITE command truncated");
569         }
570         break;
571     case C1222_CMD_WAIT:
572         if (*length >= 1) {
573             wait_seconds = tvb_get_guint8(tvb, *offset);
574             proto_tree_add_uint(tree, hf_c1222_wait_secs, tvb, *offset, 1, wait_seconds);
575             *offset += 1;
576             *length -= 1;
577             proto_item_set_text(tree, "C12.22 EPSEM: %s (%d seconds)",
578                 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), wait_seconds);
579         } else {
580             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 WAIT command truncated");
581         }
582         break;
583     case C1222_CMD_NEGOTIATE:
584         if (*length >= 3) {
585             packet_size = tvb_get_ntohs(tvb, *offset);
586             proto_tree_add_uint(tree, hf_c1222_neg_pkt_size, tvb, *offset, 2, packet_size);
587             *offset += 2;
588             *length -= 2;
589             nbr_packet = tvb_get_guint8(tvb, *offset);
590             proto_tree_add_uint(tree, hf_c1222_neg_nbr_pkts, tvb, *offset, 1, nbr_packet);
591             *offset += 1;
592             *length -= 1;
593             proto_item_set_text(tree, "C12.22 EPSEM: %s (pkt size %d, num pkts %d, with %d baud rates)",
594                     val_to_str(cmd,commandnames,"Unknown (0x%02x)"), packet_size, nbr_packet, numrates);
595         } else {
596             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 NEGOTIATE command truncated");
597         }
598         break;
599     case C1222_CMD_TIMING_SETUP:
600         if (*length >= 4) {
601             traffic = tvb_get_guint8(tvb, *offset);
602             proto_tree_add_uint(tree, hf_c1222_timing_setup_traffic, tvb, *offset, 1, traffic);
603             *offset += 1;
604             *length -= 1;
605             inter_char = tvb_get_guint8(tvb, *offset);
606             proto_tree_add_uint(tree, hf_c1222_timing_setup_inter_char, tvb, *offset, 1, inter_char);
607             *offset += 1;
608             *length -= 1;
609             resp_to = tvb_get_guint8(tvb, *offset);
610             proto_tree_add_uint(tree, hf_c1222_timing_setup_resp_to, tvb, *offset, 1, resp_to);
611             *offset += 1;
612             *length -= 1;
613             nbr_retries = tvb_get_guint8(tvb, *offset);
614             proto_tree_add_uint(tree, hf_c1222_timing_setup_nbr_retries, tvb, *offset, 1, nbr_retries);
615             *offset += 1;
616             *length -= 1;
617             proto_item_set_text(tree, "C12.22 EPSEM: %s (traffic to %d s, inter-char to %d s, response to %d s, %d retries)",
618                     val_to_str(cmd,commandnames,"Unknown (0x%02x)"), traffic, inter_char, resp_to, nbr_retries);
619         } else {
620             expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 NEGOTIATE command truncated");
621         }
622         break;
623
624     default:
625         /* don't do anything */
626         proto_item_set_text(tree, "C12.22 EPSEM: %s", val_to_str(cmd, commandnames, "Unknown (0x%02x)"));
627         if (*length) {
628             if (*length >= *length) {
629               proto_tree_add_item(tree, hf_c1222_data, tvb, *offset, *length, ENC_NA);
630             } else {
631                 expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 unknown command truncated");
632             }
633         }
634         break;
635   }
636 }
637
638 #ifdef HAVE_LIBGCRYPT
639 typedef struct tagTOP_ELEMENT_CONTROL 
640 {
641   /* TRUE if this tag is required */
642   gboolean required;
643   /* TRUE if we must truncate this tag */
644   gboolean truncate;
645   /* actual hex value of the tag we're seeking */
646   guint8 tag;
647   /* if TRUE, add tag and length before copying */
648   gboolean addtag;
649   /* pointer to pointer to memory copy of element */
650   guint8 **element;
651   /* pointer to element length */
652   guint32 *length;
653 } TOP_ELEMENT_CONTROL;
654
655 static const TOP_ELEMENT_CONTROL canonifyTable[] = {
656   { FALSE, FALSE, 0xA1, TRUE, &aSO_context, &aSO_context_len },
657   { TRUE , FALSE, 0xA2, TRUE, &called_AP_title, &called_AP_title_len },
658   { FALSE, FALSE, 0xA4, TRUE, &called_AP_invocation_id, &called_AP_invocation_id_len },
659   { FALSE, FALSE, 0xA3, TRUE, &calling_AE_qualifier, &calling_AE_qualifier_len },
660   { TRUE,  FALSE, 0xA8, TRUE, &calling_AP_invocation_id, &calling_AP_invocation_id_len },
661   { FALSE, FALSE, 0x8B, TRUE, &mechanism_name, &mechanism_name_len },
662   { FALSE, FALSE, 0xAC, TRUE, &calling_authentication_value, &calling_authentication_value_len },
663   { TRUE , TRUE , 0xBE, TRUE, &user_information, &user_information_len },
664   { FALSE, FALSE, 0xA6, TRUE, &calling_AP_title, &calling_AP_title_len },
665   { FALSE, FALSE, 0xAC, FALSE, &key_id_element, &key_id_element_len },
666   { FALSE, FALSE, 0xAC, FALSE, &iv_element, &iv_element_len },
667   { FALSE, FALSE, 0x0,  TRUE, NULL, NULL }
668 };
669
670 /**
671  * Calculates the size of the passed number n as encoded as a BER length field.
672  *
673  * \param n is the length value to be BER encoded
674  * \returns the sized of the encoding
675  */
676 static guint32
677 get_ber_len_size(guint32 n)
678 {
679   guint32 len = 1;
680   if (n > 0x7f) len++;
681   if (n > 0xff) len++;
682   if (n > 0xffff) len++;
683   if (n > 0xffffff) len++;
684   return len;
685 }
686 /**
687  * Encodes the passed value n as a BER-encoded length at puts it in memory.
688  *
689  * \param ptr points to the buffer to be written
690  * \param n is the length to be BER encoded
691  * \maxsize is the maximum number of bytes we're allowed to write
692  * \returns length of encoded value in bytes
693  */
694 static int
695 encode_ber_len(guint8 *ptr, guint32 n, int maxsize)
696 {
697   int len = get_ber_len_size(n);
698   if (len > maxsize) return 0;
699   if (len == 1) {
700     *ptr = 0x7f & n;
701   } else {
702     *ptr = (len -1) | 0x80;
703     for (ptr += len-1; n; n >>= 8)
704       *ptr-- = n & 0xff;
705   } 
706   return len;
707
708 }
709     
710 /**
711  * Checks a new encryption table item for validity.
712  *
713  * \param n points to the new record
714  * \param err is updated to point to an error string if needed
715  */
716 static void
717 c1222_uat_data_update_cb(void* n, const char** err) 
718 {
719   c1222_uat_data_t* new_rec = n;
720
721   if (new_rec->keynum > 0xff) {
722     *err = "Invalid key number; must be less than 256";
723   }
724   if (new_rec->keylen != EAX_SIZEOF_KEY) {
725     *err = "Invalid key size; must be 16 bytes";
726   }
727 }
728
729 /**
730  * Canonifies header fields in preparation for authenticating and/or decrypting the packet.
731  *
732  * \param buff points to the allocated canonization buffer
733  * \param offset points to start of unallocated space in buffer and 
734       is updated as we put bytes into buffer
735  * \param buffsize total size of allocated buffer
736  * \return FALSE if element is required and not present; otherwise TRUE 
737  */
738 static gboolean
739 canonify_unencrypted_header(guchar *buff, guint32 *offset, guint32 buffsize)
740 {
741   const TOP_ELEMENT_CONTROL *t = canonifyTable;
742   guint32 len;
743
744   for (t = canonifyTable; t->element != NULL; t++) 
745   {
746     len = *(t->length);
747     if (t->required && *(t->element) == NULL) 
748       return FALSE;
749     if (*(t->element) != NULL) {
750       if (t->addtag) { 
751         /* recreate original tag and length */
752         buff[(*offset)++] = t->tag;
753         (*offset) += encode_ber_len(&buff[*offset], len, 4);
754       } 
755       if (t->truncate) {
756         len = 3+2*get_ber_len_size(len);
757       }
758       /* bail out if the cannonization buffer is too small */
759       /* this should never happen! */
760       if (buffsize < *offset + len) {
761         return FALSE;
762       }
763       memcpy(&buff[*offset], *(t->element), len);
764       (*offset) += len;
765       g_free(*(t->element));
766       *(t->element) = NULL;
767     }
768   }
769   return TRUE;
770 }
771
772 /**
773  * Looks up the required key in the key table.
774  *
775  * \param keybuf is updated with a copy of the key data if successful lookup.
776  * \param keyid is the ID number of the desired key
777  * \returns TRUE if key was found; otherwise FALSE
778  */
779 static gboolean 
780 keylookup(guint8 *keybuff, guint8 keyid)
781 {
782   guint i;
783
784   if (c1222_uat_data == NULL)
785     return FALSE;
786   for (i = 0; i < num_c1222_uat_data; i++) {
787     if (c1222_uat_data[i].keynum == keyid) {
788       memcpy(keybuff, c1222_uat_data[i].key, EAX_SIZEOF_KEY);
789       return TRUE;
790     }
791   }
792   return FALSE;
793 }
794 #endif /* HAVE_LIBGCRYPT */
795
796 /**
797  * Authenticates and decrypts the passed packet.
798  *
799  * \param buffer points to a memory copy of the packet to be authenticated/decrypted 
800  *      and contains the decrypted value on successful return.
801  * \param length lenth of input packet
802  * \param decrypt TRUE if packet is to be authenticated and decrypted; FALSE if authentication only is requested
803  * \returns TRUE if the requested operation was successful; otherwise FALSE
804  */
805 #ifdef HAVE_LIBGCRYPT
806 static gboolean 
807 decrypt_packet(guchar *buffer, guint32 length, gboolean decrypt)
808 {
809 #define CANONBUFFSIZE 300U
810   guchar canonbuff[CANONBUFFSIZE];
811   guint8 c1222_key[EAX_SIZEOF_KEY];
812   guchar key_id = 0;
813   guint32 offset = 0;
814   gboolean status = FALSE;
815
816   /* must be at least 4 bytes long to include the MAC */
817   if (length < 4) 
818     return status;
819   if (key_id_element != NULL)
820     key_id = key_id_element[0];
821   /* extract unencrypted header information */
822   if (!canonify_unencrypted_header(canonbuff, &offset, CANONBUFFSIZE))
823     return status;
824   /* decrypt and authenticate in place */
825 /* PARAMETERS:     pN     : Pointer to ClearText (Input, Canonified form).    */
826 /*                 pK     : Pointer to secret key (Input).                    */
827 /*                 pC     : Pointer to CipherText (Input/Output).             */
828 /*                 SizeN  : Byte length of ClearText buffer.                  */
829 /*                 SizeK  : Byte length of secret key.                        */
830 /*                 SizeC  : Byte length of CipherText buffer.                 */
831 /*                 pMac   : Four byte Message Authentication Code.            */
832 /*                 Mode   : Operating mode (See EAX_MODE_xxx).                */
833 /* RETURNS:        TRUE if message has been authenticated.                    */
834 /*                 FALSE if not authenticated, invalid Mode, or error.        */
835   if (offset) {
836     if (!keylookup((guint8 *)&c1222_key, key_id)) 
837       return FALSE;
838     status = Eax_Decrypt(canonbuff, c1222_key, buffer,
839                   offset, EAX_SIZEOF_KEY, length-4, 
840                   (MAC_T *)&buffer[length-4], 
841                   decrypt ? EAX_MODE_CIPHERTEXT_AUTH : EAX_MODE_CLEARTEXT_AUTH);
842   }
843   return status;
844 }
845 #else /* HAVE_LIBCRYPT */  
846 static gboolean 
847 decrypt_packet(guchar *buffer _U_, guint32 length _U_, gboolean decrypt _U_)
848 {
849   return FALSE;
850 }
851 #endif /* HAVE_LIBGCRYPT */
852
853 /**
854  * Checks to make sure that a complete, valid BER-encoded length is in the buffer.
855  *
856  * \param tvb contains the buffer to be examined
857  * \param offset is the offset within the buffer at which the BER-encded length begins
858  * \returns TRUE if a complete, valid BER-encoded length is in the buffer; otherwise FALSE
859  */
860 static gboolean
861 ber_len_ok(tvbuff_t *tvb, int offset)
862 {
863   guint8 ch;
864
865   if (tvb_offset_exists(tvb, offset)) {
866     ch = tvb_get_guint8(tvb, offset);
867     offset++;
868     if (!(ch & 0x80)) {
869       return TRUE;
870     } else if (tvb_offset_exists(tvb, offset)) {
871       ch = tvb_get_guint8(tvb, offset);
872       offset++;
873       if (!(ch & 0x80)) {
874         return TRUE;
875       } else if (tvb_offset_exists(tvb, offset)) {
876         ch = tvb_get_guint8(tvb, offset);
877         offset++;
878         if (!(ch & 0x80)) {
879           return TRUE;
880         } else if (tvb_offset_exists(tvb, offset)) {
881           ch = tvb_get_guint8(tvb, offset);
882           /*offset++;*/
883           if (!(ch & 0x80)) {
884             return TRUE;
885           }
886         }
887       }
888     }
889   }
890   return FALSE;
891 }
892
893 /**
894  * Dissects the EPSEM portion of the User-information part of a C12.22 message.
895  *
896  * \param tvb
897  * \param offset
898  * \param len
899  * \param pinfo
900  * \param tree
901  */
902 static int
903 dissect_epsem(tvbuff_t *tvb, int offset, guint32 len, packet_info *pinfo, proto_tree *tree)
904 {
905   proto_tree *cmd_tree = NULL;
906   proto_tree *ct = NULL;
907   proto_tree *crypto_tree = NULL;
908   proto_tree *yt = NULL;
909   proto_item *item = NULL;
910   guint8 flags;
911   int local_offset;
912   guint32 len2;
913   int cmd_err;
914   gboolean ind;
915   guchar *buffer;
916   tvbuff_t *epsem_buffer = NULL;
917   gboolean crypto_good = FALSE;
918   gboolean crypto_bad = FALSE;
919   gboolean hasmac = FALSE;
920   gboolean encrypted = FALSE;
921
922   if ((tvb == NULL) && (len == 0)) {
923       expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 EPSEM missing");
924       return offset;
925   }
926   /* parse the flags byte which is always unencrypted */
927   flags = tvb_get_guint8(tvb, offset);
928   proto_tree_add_bitmask(tree, tvb, offset, hf_c1222_epsem_flags, ett_c1222_flags, c1222_flags, ENC_BIG_ENDIAN);
929   offset++;
930   switch ((flags & C1222_EPSEM_FLAG_SECURITY_MODE) >> 2) {
931     case EAX_MODE_CIPHERTEXT_AUTH:
932       /* mode is ciphertext with authentication */
933       hasmac = TRUE;
934       len2 = tvb_length_remaining(tvb, offset);
935       if (len2 <= 0)
936         return offset; 
937       encrypted = TRUE;
938       if (c1222_decrypt) {
939         buffer = tvb_memdup(tvb, offset, len2);
940         if (!decrypt_packet(buffer, len2, TRUE)) {
941           g_free(buffer);
942           crypto_bad = TRUE;
943         } else {
944           epsem_buffer = tvb_new_real_data(buffer, len2, len2);
945           tvb_set_child_real_data_tvbuff(tvb, epsem_buffer);
946           add_new_data_source(pinfo, epsem_buffer, "Decrypted EPSEM Data");
947           crypto_good = TRUE;
948           encrypted = FALSE;
949         }
950       }
951       break;
952     case EAX_MODE_CLEARTEXT_AUTH:
953       /* mode is cleartext with authentication */
954       hasmac = TRUE;
955       len2 = tvb_length_remaining(tvb, offset);
956       if (len2 <= 0)
957         return offset;
958       buffer = tvb_memdup(tvb, offset, len2);
959       epsem_buffer = tvb_new_subset(tvb, offset, -1, -1);
960       if (c1222_decrypt) {
961         if (!decrypt_packet(buffer, len2, FALSE)) {
962 #ifdef HAVE_LIBGCRYPT
963           crypto_bad = TRUE;
964           expert_add_info_format(pinfo, tree, PI_SECURITY, PI_ERROR, "C12.22 EPSEM failed authentication");
965 #else /* HAVE_LIBGCRYPT */
966           expert_add_info_format(pinfo, tree, PI_SECURITY, PI_WARN, "C12.22 EPSEM could not be authenticated");
967 #endif /* HAVE_LIBGCRYPT */
968         } else {
969           crypto_good = TRUE;
970         }
971       }
972       break;
973     default:
974       /* it's not encrypted */
975       epsem_buffer = tvb_new_subset(tvb, offset, -1, -1);
976   }
977   /* it's only encrypted if we have an undecrypted payload */
978   if (encrypted) {
979     proto_tree_add_item(tree, hf_c1222_epsem_total, tvb, offset, -1, ENC_NA); 
980     expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN, "C12.22 EPSEM could not be decrypted");
981     local_offset = offset+len2-4;
982     epsem_buffer = tvb;
983   } else {  /* it's not (now) encrypted */
984     local_offset = 0;
985     /* retrieve the ed_class if it's there */
986     if (flags & C1222_EPSEM_FLAG_ED_CLASS_INCLUDED) {
987       if (tvb_offset_exists(epsem_buffer, local_offset+4-1)) {
988         proto_tree_add_item(tree, hf_c1222_epsem_ed_class, epsem_buffer, local_offset, 4, ENC_NA);
989         local_offset += 4;
990       } else {
991         expert_add_info_format(pinfo, tree, PI_SECURITY, PI_ERROR, "C12.22 ED Class missing");
992       }
993     }
994     /* what follows are one or more <epsem-data> elements possibly followed by
995      * a <mac>.  Each <epsem-data> element is defined as <service-length><res-req>, 
996      * so we fetch such pairs until there isn't anything left (except possibly
997      * the <mac>).
998      */
999     while (tvb_offset_exists(epsem_buffer, local_offset+(hasmac?5:1))) {
1000       if (ber_len_ok(epsem_buffer, local_offset)) {
1001         local_offset = dissect_ber_length(pinfo, tree, epsem_buffer, local_offset, &len2, &ind);
1002       } else {
1003         expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 EPSEM BER length error");
1004         return offset+len;
1005       }
1006       if (tvb_offset_exists(epsem_buffer, local_offset+len2-1)) {
1007         cmd_err = tvb_get_guint8(epsem_buffer, local_offset);
1008         ct = proto_tree_add_item(tree, hf_c1222_epsem_total, epsem_buffer, local_offset, len2, ENC_NA);
1009         cmd_tree = proto_item_add_subtree(ct, ett_c1222_cmd);
1010         parse_c1222_detailed(epsem_buffer, pinfo, cmd_tree, cmd_err, &len2, &local_offset);
1011         local_offset += len2;
1012       } else {
1013         expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 EPSEM field length error");
1014         return offset+len;
1015       }
1016     }
1017   }
1018   if (hasmac) {
1019     if (tvb_offset_exists(epsem_buffer, local_offset+4-1)) { 
1020       yt = proto_tree_add_item(tree, hf_c1222_epsem_mac, epsem_buffer, local_offset, 4, ENC_NA);
1021       /* now we have enough information to fill in the crypto subtree */
1022       crypto_tree = proto_item_add_subtree(yt, ett_c1222_crypto);
1023       item = proto_tree_add_boolean(crypto_tree, hf_c1222_epsem_crypto_good, tvb, local_offset, 4, crypto_good);
1024       PROTO_ITEM_SET_GENERATED(item);
1025       item = proto_tree_add_boolean(crypto_tree, hf_c1222_epsem_crypto_bad, tvb, local_offset, 4, crypto_bad);
1026       PROTO_ITEM_SET_GENERATED(item);
1027     } else {
1028       expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR, "C12.22 MAC missing");
1029       return offset+len;
1030     }
1031   }
1032   return offset;
1033 }
1034
1035
1036 /*--- Included file: packet-c1222-fn.c ---*/
1037 #line 1 "../../asn1/c1222/packet-c1222-fn.c"
1038
1039
1040 static int
1041 dissect_c1222_ASO_qualifier(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1042 #line 50 "../../asn1/c1222/c1222.cnf"
1043   FILL_START;
1044     offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1045
1046   FILL_TABLE(aSO_context);
1047
1048
1049
1050   return offset;
1051 }
1052
1053
1054
1055 static int
1056 dissect_c1222_AP_title(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1057   offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1058
1059   return offset;
1060 }
1061
1062
1063
1064 static int
1065 dissect_c1222_Called_AP_title(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1066 #line 55 "../../asn1/c1222/c1222.cnf"
1067   FILL_START;
1068     offset = dissect_c1222_AP_title(implicit_tag, tvb, offset, actx, tree, hf_index);
1069
1070   FILL_TABLE(called_AP_title);
1071
1072
1073
1074   return offset;
1075 }
1076
1077
1078
1079 static int
1080 dissect_c1222_AP_invocation_id(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1081   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1082                                                 NULL);
1083
1084   return offset;
1085 }
1086
1087
1088
1089 static int
1090 dissect_c1222_Called_AP_invocation_id(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1091 #line 60 "../../asn1/c1222/c1222.cnf"
1092   FILL_START;
1093     offset = dissect_c1222_AP_invocation_id(implicit_tag, tvb, offset, actx, tree, hf_index);
1094
1095   FILL_TABLE(called_AP_invocation_id);
1096
1097
1098
1099   return offset;
1100 }
1101
1102
1103
1104 static int
1105 dissect_c1222_Calling_AP_title(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1106 #line 85 "../../asn1/c1222/c1222.cnf"
1107   FILL_START;
1108     offset = dissect_c1222_AP_title(implicit_tag, tvb, offset, actx, tree, hf_index);
1109
1110   FILL_TABLE(calling_AP_title);
1111
1112
1113
1114   return offset;
1115 }
1116
1117
1118
1119 static int
1120 dissect_c1222_AE_qualifier(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1121   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1122                                                 NULL);
1123
1124   return offset;
1125 }
1126
1127
1128
1129 static int
1130 dissect_c1222_Calling_AE_qualifier(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1131 #line 65 "../../asn1/c1222/c1222.cnf"
1132   FILL_START;
1133     offset = dissect_c1222_AE_qualifier(implicit_tag, tvb, offset, actx, tree, hf_index);
1134
1135   FILL_TABLE(calling_AE_qualifier);
1136
1137
1138
1139   return offset;
1140 }
1141
1142
1143
1144 static int
1145 dissect_c1222_Calling_AP_invocation_id(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1146 #line 70 "../../asn1/c1222/c1222.cnf"
1147   FILL_START;
1148     offset = dissect_c1222_AP_invocation_id(implicit_tag, tvb, offset, actx, tree, hf_index);
1149
1150   FILL_TABLE(calling_AP_invocation_id);
1151
1152
1153
1154   return offset;
1155 }
1156
1157
1158
1159 static int
1160 dissect_c1222_Mechanism_name(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1161 #line 75 "../../asn1/c1222/c1222.cnf"
1162   FILL_START;
1163     offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1164
1165   FILL_TABLE(mechanism_name);
1166
1167
1168
1169   return offset;
1170 }
1171
1172
1173
1174 static int
1175 dissect_c1222_INTEGER(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1176   offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1177                                                 NULL);
1178
1179   return offset;
1180 }
1181
1182
1183
1184 static int
1185 dissect_c1222_Key_id_element(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1186 #line 90 "../../asn1/c1222/c1222.cnf"
1187   FILL_START;
1188     offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1189                                        NULL);
1190
1191   FILL_TABLE(key_id_element);
1192
1193
1194
1195   return offset;
1196 }
1197
1198
1199
1200 static int
1201 dissect_c1222_Iv_element(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1202 #line 95 "../../asn1/c1222/c1222.cnf"
1203   FILL_START;
1204     offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1205                                        NULL);
1206
1207   FILL_TABLE(iv_element);
1208
1209
1210
1211   return offset;
1212 }
1213
1214
1215 static const ber_sequence_t Calling_authentication_value_c1222_U_sequence[] = {
1216   { &hf_c1222_key_id_element, BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_c1222_Key_id_element },
1217   { &hf_c1222_iv_element    , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_c1222_Iv_element },
1218   { NULL, 0, 0, 0, NULL }
1219 };
1220
1221 static int
1222 dissect_c1222_Calling_authentication_value_c1222_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1223   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1224                                    Calling_authentication_value_c1222_U_sequence, hf_index, ett_c1222_Calling_authentication_value_c1222_U);
1225
1226   return offset;
1227 }
1228
1229
1230
1231 static int
1232 dissect_c1222_Calling_authentication_value_c1222(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1233   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1234                                       hf_index, BER_CLASS_CON, 1, TRUE, dissect_c1222_Calling_authentication_value_c1222_U);
1235
1236   return offset;
1237 }
1238
1239
1240
1241 static int
1242 dissect_c1222_OCTET_STRING_SIZE_CONSTR001(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1243   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1244                                        NULL);
1245
1246   return offset;
1247 }
1248
1249
1250
1251 static int
1252 dissect_c1222_OCTET_STRING_SIZE_1_255(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1253   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1254                                        NULL);
1255
1256   return offset;
1257 }
1258
1259
1260
1261 static int
1262 dissect_c1222_OCTET_STRING_SIZE_CONSTR002(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1263   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1264                                        NULL);
1265
1266   return offset;
1267 }
1268
1269
1270 static const value_string c1222_Calling_authentication_value_c1221_U_vals[] = {
1271   {   0, "c1221-auth-identification" },
1272   {   0, "c1221-auth-request" },
1273   {   0, "c1221-auth-response" },
1274   { 0, NULL }
1275 };
1276
1277 static const ber_choice_t Calling_authentication_value_c1221_U_choice[] = {
1278   {   0, &hf_c1222_c1221_auth_identification, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING_SIZE_CONSTR001 },
1279   {   0, &hf_c1222_c1221_auth_request, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING_SIZE_1_255 },
1280   {   0, &hf_c1222_c1221_auth_response, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING_SIZE_CONSTR002 },
1281   { 0, NULL, 0, 0, 0, NULL }
1282 };
1283
1284 static int
1285 dissect_c1222_Calling_authentication_value_c1221_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1286   offset = dissect_ber_choice(actx, tree, tvb, offset,
1287                                  Calling_authentication_value_c1221_U_choice, hf_index, ett_c1222_Calling_authentication_value_c1221_U,
1288                                  NULL);
1289
1290   return offset;
1291 }
1292
1293
1294
1295 static int
1296 dissect_c1222_Calling_authentication_value_c1221(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1297   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1298                                       hf_index, BER_CLASS_CON, 0, TRUE, dissect_c1222_Calling_authentication_value_c1221_U);
1299
1300   return offset;
1301 }
1302
1303
1304 static const value_string c1222_Calling_authentication_value_single_asn1_vals[] = {
1305   {   1, "calling-authentication-value-c1222" },
1306   {   0, "calling-authentication-value-c1221" },
1307   { 0, NULL }
1308 };
1309
1310 static const ber_choice_t Calling_authentication_value_single_asn1_choice[] = {
1311   {   1, &hf_c1222_calling_authentication_value_c1222, BER_CLASS_CON, 1, BER_FLAGS_NOOWNTAG, dissect_c1222_Calling_authentication_value_c1222 },
1312   {   0, &hf_c1222_calling_authentication_value_c1221, BER_CLASS_CON, 0, BER_FLAGS_NOOWNTAG, dissect_c1222_Calling_authentication_value_c1221 },
1313   { 0, NULL, 0, 0, 0, NULL }
1314 };
1315
1316 static int
1317 dissect_c1222_Calling_authentication_value_single_asn1(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1318   offset = dissect_ber_choice(actx, tree, tvb, offset,
1319                                  Calling_authentication_value_single_asn1_choice, hf_index, ett_c1222_Calling_authentication_value_single_asn1,
1320                                  NULL);
1321
1322   return offset;
1323 }
1324
1325
1326
1327 static int
1328 dissect_c1222_OCTET_STRING(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1329   offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1330                                        NULL);
1331
1332   return offset;
1333 }
1334
1335
1336 static const value_string c1222_Authentication_value_encoding_vals[] = {
1337   {   0, "calling-authentication-value-single-asn1" },
1338   {   1, "calling-authentication-value-octet-aligned" },
1339   { 0, NULL }
1340 };
1341
1342 static const ber_choice_t Authentication_value_encoding_choice[] = {
1343   {   0, &hf_c1222_calling_authentication_value_single_asn1, BER_CLASS_CON, 0, 0, dissect_c1222_Calling_authentication_value_single_asn1 },
1344   {   1, &hf_c1222_calling_authentication_value_octet_aligned, BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING },
1345   { 0, NULL, 0, 0, 0, NULL }
1346 };
1347
1348 static int
1349 dissect_c1222_Authentication_value_encoding(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1350   offset = dissect_ber_choice(actx, tree, tvb, offset,
1351                                  Authentication_value_encoding_choice, hf_index, ett_c1222_Authentication_value_encoding,
1352                                  NULL);
1353
1354   return offset;
1355 }
1356
1357
1358 static const ber_sequence_t Calling_authentication_value_U_sequence[] = {
1359   { &hf_c1222_calling_authentication_value_indirect, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_c1222_INTEGER },
1360   { &hf_c1222_calling_authentication_value_encoding, BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_c1222_Authentication_value_encoding },
1361   { NULL, 0, 0, 0, NULL }
1362 };
1363
1364 static int
1365 dissect_c1222_Calling_authentication_value_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1366   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1367                                    Calling_authentication_value_U_sequence, hf_index, ett_c1222_Calling_authentication_value_U);
1368
1369   return offset;
1370 }
1371
1372
1373
1374 static int
1375 dissect_c1222_Calling_authentication_value(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1376 #line 80 "../../asn1/c1222/c1222.cnf"
1377   FILL_START;
1378     offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1379                                       hf_index, BER_CLASS_CON, 2, TRUE, dissect_c1222_Calling_authentication_value_U);
1380
1381   FILL_TABLE(calling_authentication_value);
1382
1383
1384
1385   return offset;
1386 }
1387
1388
1389
1390 static int
1391 dissect_c1222_User_information(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1392 #line 26 "../../asn1/c1222/c1222.cnf"
1393   gint8 class;
1394   gboolean pc, ind;
1395   gint32 tag;
1396   guint32 len;
1397   proto_item *tf = NULL;
1398   proto_tree *epsem_tree = NULL;
1399   FILL_START;
1400   
1401   /* get Tag and Length */
1402   offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1403   offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1404   FILL_TABLE_TRUNCATE(user_information, len+offset-start_offset);
1405   if (tag == 0x8) {  /* BER_TAG_EXTERNAL */
1406     offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &class, &pc, &tag);
1407     offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1408     if (tag == 0x1) { /* implicit octet string */
1409       tf = proto_tree_add_item(tree, hf_c1222_user_information, tvb, offset, len, ENC_NA);
1410       epsem_tree = proto_item_add_subtree(tf, ett_c1222_epsem);
1411       dissect_epsem(tvb, offset, len, actx->pinfo, epsem_tree);
1412       offset += len;
1413     }
1414   }
1415
1416
1417
1418   return offset;
1419 }
1420
1421
1422 static const ber_sequence_t C1222_MESSAGE_U_sequence[] = {
1423   { &hf_c1222_aSO_context   , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_c1222_ASO_qualifier },
1424   { &hf_c1222_called_AP_title, BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_c1222_Called_AP_title },
1425   { &hf_c1222_called_AP_invocation_id, BER_CLASS_CON, 4, BER_FLAGS_OPTIONAL, dissect_c1222_Called_AP_invocation_id },
1426   { &hf_c1222_calling_AP_title, BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL, dissect_c1222_Calling_AP_title },
1427   { &hf_c1222_calling_AE_qualifier, BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL, dissect_c1222_Calling_AE_qualifier },
1428   { &hf_c1222_calling_AP_invocation_id, BER_CLASS_CON, 8, 0, dissect_c1222_Calling_AP_invocation_id },
1429   { &hf_c1222_mechanism_name, BER_CLASS_CON, 11, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_c1222_Mechanism_name },
1430   { &hf_c1222_calling_authentication_value, BER_CLASS_CON, 12, BER_FLAGS_OPTIONAL, dissect_c1222_Calling_authentication_value },
1431   { &hf_c1222_user_information, BER_CLASS_CON, 30, 0, dissect_c1222_User_information },
1432   { NULL, 0, 0, 0, NULL }
1433 };
1434
1435 static int
1436 dissect_c1222_C1222_MESSAGE_U(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1437   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1438                                    C1222_MESSAGE_U_sequence, hf_index, ett_c1222_C1222_MESSAGE_U);
1439
1440   return offset;
1441 }
1442
1443
1444
1445 static int
1446 dissect_c1222_C1222_MESSAGE(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1447   offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1448                                       hf_index, BER_CLASS_APP, 0, TRUE, dissect_c1222_C1222_MESSAGE_U);
1449
1450   return offset;
1451 }
1452
1453 /*--- PDUs ---*/
1454
1455 static void dissect_C1222_MESSAGE_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {
1456   asn1_ctx_t asn1_ctx;
1457   asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1458   dissect_c1222_C1222_MESSAGE(FALSE, tvb, 0, &asn1_ctx, tree, hf_c1222_C1222_MESSAGE_PDU);
1459 }
1460
1461
1462 /*--- End of included file: packet-c1222-fn.c ---*/
1463 #line 991 "../../asn1/c1222/packet-c1222-template.c"
1464
1465 /**
1466  * Dissects a a full (reassembled) C12.22 message.
1467  *
1468  * \param tvb
1469  * \param pinfo
1470  * \param tree
1471  */
1472 static void
1473 dissect_c1222_full(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1474 {
1475     proto_item      *c1222_item = NULL;
1476     proto_tree      *c1222_tree = NULL;
1477
1478     /* make entry in the Protocol column on summary display */
1479     col_set_str(pinfo->cinfo, COL_PROTOCOL, PNAME);
1480
1481     /* create the c1222 protocol tree */
1482     if (tree) {
1483         c1222_item = proto_tree_add_item(tree, proto_c1222, tvb, 0, -1, ENC_NA);
1484         c1222_tree = proto_item_add_subtree(c1222_item, ett_c1222);
1485         dissect_C1222_MESSAGE_PDU(tvb, pinfo, c1222_tree);
1486     }
1487 }
1488
1489 /**
1490  * Fetches the length of an entire C12.22 message to assist in reassembly.
1491  *
1492  * \param pinfo
1493  * \param tvb
1494  * \param offset
1495  * \returns length of entire C12.22 message
1496  */
1497 static guint
1498 get_c1222_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
1499 {
1500   int orig_offset;
1501   guint length;
1502   gboolean ind;
1503
1504   orig_offset = offset;
1505   /* note that this assumes a Tag length of 1 which is always valid for C12.22 */
1506   offset = dissect_ber_length(pinfo, NULL, tvb, offset+1, &length, &ind);
1507   return length+(offset - orig_offset);
1508 }
1509
1510 /**
1511  * Reassembles and dissects C12.22 messages.
1512  *
1513  * \param tvb
1514  * \param pinfo
1515  * \param tree
1516  */
1517 static void 
1518 dissect_c1222(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1519 {
1520     tcp_dissect_pdus(tvb, pinfo, tree, c1222_desegment, 5, 
1521             get_c1222_message_len, dissect_c1222_full);
1522 }
1523
1524 /*--- proto_register_c1222 -------------------------------------------*/
1525 void proto_register_c1222(void) {
1526
1527   /* List of fields */
1528   static hf_register_info hf[] = {
1529    { &hf_c1222_epsem_flags,
1530     { "C12.22 EPSEM Flags", "c1222.epsem.flags",
1531     FT_UINT8, BASE_HEX,
1532     NULL, 0x0,
1533     NULL, HFILL }
1534    },
1535    { &hf_c1222_epsem_flags_reserved,
1536     { "C12.22 Reserved Flag", "c1222.epsem.flags.reserved",
1537     FT_BOOLEAN, 8,
1538     NULL, C1222_EPSEM_FLAG_RESERVED,
1539     NULL, HFILL }
1540    },
1541    { &hf_c1222_epsem_flags_recovery,
1542     { "C12.22 Recovery Flag", "c1222.epsem.flags.recovery",
1543     FT_BOOLEAN, 8,
1544     NULL, C1222_EPSEM_FLAG_RECOVERY_SESSION,
1545     NULL, HFILL }
1546    },
1547    { &hf_c1222_epsem_flags_proxy,
1548     { "C12.22 Proxy Service Used Flag", "c1222.epsem.flags.proxy",
1549     FT_BOOLEAN, 8,
1550     NULL, C1222_EPSEM_FLAG_PROXY_SERVICE_USED,
1551     NULL, HFILL }
1552    },
1553    { &hf_c1222_epsem_flags_ed_class,
1554     { "C12.22 ED Class Flag", "c1222.epsem.flags.ed_class",
1555     FT_BOOLEAN, 8,
1556     NULL, C1222_EPSEM_FLAG_ED_CLASS_INCLUDED,
1557     NULL, HFILL }
1558    },
1559    { &hf_c1222_epsem_flags_security_modes,
1560     { "C12.22 Security Mode Flags", "c1222.epsem.flags.security",
1561     FT_UINT8, BASE_HEX,
1562     VALS(c1222_security_modes), C1222_EPSEM_FLAG_SECURITY_MODE,
1563     NULL, HFILL }
1564    },
1565    { &hf_c1222_epsem_flags_response_control,
1566     { "C12.22 Response Control Flags", "c1222.epsem.flags.response_control",
1567     FT_UINT8, BASE_HEX,
1568     VALS(c1222_response_control), C1222_EPSEM_FLAG_RESPONSE_CONTROL,
1569     NULL, HFILL }
1570    },
1571    { &hf_c1222_epsem_ed_class,
1572     { "C12.22 EPSEM ED Class", "c1222.epsem.edclass",
1573     FT_BYTES, BASE_NONE,
1574     NULL, 0x0,
1575     NULL, HFILL }
1576    },
1577    { &hf_c1222_epsem_total,
1578     { "C12.22 EPSEM", "c1222.epsem.data",
1579     FT_BYTES, BASE_NONE,
1580     NULL, 0x0,
1581     NULL, HFILL }
1582    },
1583    { &hf_c1222_epsem_mac,
1584     { "C12.22 EPSEM MAC", "c1222.epsem.mac",
1585     FT_BYTES, BASE_NONE,
1586     NULL, 0x0,
1587     NULL, HFILL }
1588    },
1589    { &hf_c1222_cmd,
1590     { "C12.22 Command", "c1222.cmd",
1591     FT_UINT8, BASE_HEX,
1592     VALS(commandnames), 0x0,
1593     NULL, HFILL }
1594    },
1595    { &hf_c1222_err,
1596     { "C12.22 Response", "c1222.err",
1597     FT_UINT8, BASE_HEX,
1598     VALS(commandnames), 0x0,
1599     NULL, HFILL }
1600    },
1601    { &hf_c1222_logon_id,
1602     { "C12.22 Logon User-Id", "c1222.logon.id",
1603     FT_UINT16, BASE_DEC,
1604     NULL, 0x0,
1605     NULL, HFILL }
1606    },
1607    { &hf_c1222_logon_user,
1608     { "C12.22 Logon User", "c1222.logon.user",
1609     FT_STRING, BASE_NONE,
1610     NULL, 0x0,
1611     NULL, HFILL }
1612    },
1613    { &hf_c1222_security_password,
1614     { "C12.22 Security Password", "c1222.security.password",
1615     FT_STRING, BASE_NONE,
1616     NULL, 0x0,
1617     NULL, HFILL }
1618    },
1619    { &hf_c1222_auth_len,
1620     { "C12.22 Authenticate Request Length", "c1222.authenticate.len",
1621     FT_UINT8, BASE_DEC,
1622     NULL, 0x0,
1623     NULL, HFILL }
1624    },
1625    { &hf_c1222_auth_data,
1626     { "C12.22 Authenticate Data", "c1222.authenticate.data",
1627     FT_BYTES, BASE_NONE,
1628     NULL, 0x0,
1629     NULL, HFILL }
1630    },
1631    { &hf_c1222_read_table,
1632     { "C12.22 Table", "c1222.read.table",
1633     FT_UINT16, BASE_HEX,
1634     NULL, 0x0,
1635     NULL, HFILL }
1636    },
1637    { &hf_c1222_read_offset,
1638     { "C12.22 Offset", "c1222.read.offset",
1639     FT_UINT24, BASE_HEX,
1640     NULL, 0x0,
1641     NULL, HFILL }
1642    },
1643    { &hf_c1222_read_count,
1644     { "C12.22 Count", "c1222.read.count",
1645     FT_UINT16, BASE_DEC,
1646     NULL, 0x0,
1647     NULL, HFILL }
1648    },
1649    { &hf_c1222_write_table,
1650     { "C12.22 Table", "c1222.write.table",
1651     FT_UINT16, BASE_HEX,
1652     NULL, 0x0,
1653     NULL, HFILL }
1654    },
1655    { &hf_c1222_write_offset,
1656     { "C12.22 Offset", "c1222.write.offset",
1657     FT_UINT24, BASE_HEX,
1658     NULL, 0x0,
1659     NULL, HFILL }
1660    },
1661    { &hf_c1222_write_size,
1662     { "C12.22 Table Size", "c1222.write.size",
1663     FT_UINT16, BASE_HEX,
1664     NULL, 0x0,
1665     NULL, HFILL }
1666    },
1667    { &hf_c1222_write_data,
1668     { "C12.22 Table Data", "c1222.write.data",
1669     FT_BYTES, BASE_NONE,
1670     NULL, 0x0,
1671     NULL, HFILL }
1672    },
1673    { &hf_c1222_write_chksum,
1674     { "C12.22 Table Data Checksum", "c1222.write.chksum",
1675     FT_UINT8, BASE_HEX,
1676     NULL, 0x0,
1677     NULL, HFILL }
1678    },
1679    { &hf_c1222_neg_pkt_size,
1680     { "C12.22 Negotiate Packet Size", "c1222.negotiate.pktsize",
1681     FT_UINT16, BASE_DEC,
1682     NULL, 0x0,
1683     NULL, HFILL }
1684    },
1685    { &hf_c1222_neg_nbr_pkts,
1686     { "C12.22 Negotiate Number of Packets", "c1222.negotiate.numpkts",
1687     FT_UINT8, BASE_DEC,
1688     NULL, 0x0,
1689     NULL, HFILL }
1690    },
1691    { &hf_c1222_wait_secs,
1692     { "C12.22 Wait Seconds", "c1222.wait.seconds",
1693     FT_UINT8, BASE_DEC,
1694     NULL, 0x0,
1695     NULL, HFILL }
1696    },
1697    { &hf_c1222_timing_setup_traffic,
1698     { "C12.22 Timing Setup Channel Traffic Timeout", "c1222.timingsetup.traffic",
1699     FT_UINT8, BASE_DEC,
1700     NULL, 0x0,
1701     NULL, HFILL }
1702    },
1703    { &hf_c1222_timing_setup_inter_char,
1704     { "C12.22 Timing Setup Intercharacter Timeout", "c1222.timingsetup.interchar",
1705     FT_UINT8, BASE_DEC,
1706     NULL, 0x0,
1707     NULL, HFILL }
1708    },
1709    { &hf_c1222_timing_setup_resp_to,
1710     { "C12.22 Timing Setup Response Timeout", "c1222.timingsetup.respto",
1711     FT_UINT8, BASE_DEC,
1712     NULL, 0x0,
1713     NULL, HFILL }
1714    },
1715    { &hf_c1222_timing_setup_nbr_retries,
1716     { "C12.22 Timing Setup Number of Retries", "c1222.timingsetup.nbrretries",
1717     FT_UINT8, BASE_DEC,
1718     NULL, 0x0,
1719     NULL, HFILL }
1720    },
1721    { &hf_c1222_data,
1722     { "C12.22 data", "c1222.data",
1723     FT_BYTES, BASE_NONE,
1724     NULL, 0x0,
1725     NULL, HFILL }
1726    },
1727    { &hf_c1222_crc,
1728     { "C12.22 CRC", "c1222.crc",
1729     FT_UINT16, BASE_HEX,
1730     NULL, 0x0,
1731     NULL, HFILL }
1732    },
1733    { &hf_c1222_epsem_crypto_good,
1734     { "Crypto good", "c1222.crypto_good",
1735     FT_BOOLEAN, BASE_NONE,
1736     NULL, 0x0,
1737     "True: crypto ok; False: doesn't match or not checked", HFILL }
1738    },
1739    { &hf_c1222_epsem_crypto_bad,
1740     { "Crypto bad", "c1222.crypto_bad",
1741     FT_BOOLEAN, BASE_NONE,
1742     NULL, 0x0,
1743     "True: crypto bad; False: crypto ok or not checked", HFILL }
1744    },
1745
1746 /*--- Included file: packet-c1222-hfarr.c ---*/
1747 #line 1 "../../asn1/c1222/packet-c1222-hfarr.c"
1748     { &hf_c1222_C1222_MESSAGE_PDU,
1749       { "C1222-MESSAGE", "c1222.C1222_MESSAGE",
1750         FT_NONE, BASE_NONE, NULL, 0,
1751         NULL, HFILL }},
1752     { &hf_c1222_aSO_context,
1753       { "aSO-context", "c1222.aSO_context",
1754         FT_OID, BASE_NONE, NULL, 0,
1755         "ASO_qualifier", HFILL }},
1756     { &hf_c1222_called_AP_title,
1757       { "called-AP-title", "c1222.called_AP_title",
1758         FT_OID, BASE_NONE, NULL, 0,
1759         NULL, HFILL }},
1760     { &hf_c1222_called_AP_invocation_id,
1761       { "called-AP-invocation-id", "c1222.called_AP_invocation_id",
1762         FT_INT32, BASE_DEC, NULL, 0,
1763         NULL, HFILL }},
1764     { &hf_c1222_calling_AP_title,
1765       { "calling-AP-title", "c1222.calling_AP_title",
1766         FT_OID, BASE_NONE, NULL, 0,
1767         NULL, HFILL }},
1768     { &hf_c1222_calling_AE_qualifier,
1769       { "calling-AE-qualifier", "c1222.calling_AE_qualifier",
1770         FT_INT32, BASE_DEC, NULL, 0,
1771         NULL, HFILL }},
1772     { &hf_c1222_calling_AP_invocation_id,
1773       { "calling-AP-invocation-id", "c1222.calling_AP_invocation_id",
1774         FT_INT32, BASE_DEC, NULL, 0,
1775         NULL, HFILL }},
1776     { &hf_c1222_mechanism_name,
1777       { "mechanism-name", "c1222.mechanism_name",
1778         FT_OID, BASE_NONE, NULL, 0,
1779         NULL, HFILL }},
1780     { &hf_c1222_calling_authentication_value,
1781       { "calling-authentication-value", "c1222.calling_authentication_value",
1782         FT_NONE, BASE_NONE, NULL, 0,
1783         NULL, HFILL }},
1784     { &hf_c1222_user_information,
1785       { "user-information", "c1222.user_information",
1786         FT_NONE, BASE_NONE, NULL, 0,
1787         NULL, HFILL }},
1788     { &hf_c1222_calling_authentication_value_indirect,
1789       { "calling-authentication-value-indirect", "c1222.calling_authentication_value_indirect",
1790         FT_INT32, BASE_DEC, NULL, 0,
1791         "INTEGER", HFILL }},
1792     { &hf_c1222_calling_authentication_value_encoding,
1793       { "calling-authentication-value-encoding", "c1222.calling_authentication_value_encoding",
1794         FT_UINT32, BASE_DEC, VALS(c1222_Authentication_value_encoding_vals), 0,
1795         "Authentication_value_encoding", HFILL }},
1796     { &hf_c1222_calling_authentication_value_single_asn1,
1797       { "calling-authentication-value-single-asn1", "c1222.calling_authentication_value_single_asn1",
1798         FT_UINT32, BASE_DEC, VALS(c1222_Calling_authentication_value_single_asn1_vals), 0,
1799         NULL, HFILL }},
1800     { &hf_c1222_calling_authentication_value_octet_aligned,
1801       { "calling-authentication-value-octet-aligned", "c1222.calling_authentication_value_octet_aligned",
1802         FT_BYTES, BASE_NONE, NULL, 0,
1803         "OCTET_STRING", HFILL }},
1804     { &hf_c1222_calling_authentication_value_c1222,
1805       { "calling-authentication-value-c1222", "c1222.calling_authentication_value_c1222",
1806         FT_NONE, BASE_NONE, NULL, 0,
1807         NULL, HFILL }},
1808     { &hf_c1222_calling_authentication_value_c1221,
1809       { "calling-authentication-value-c1221", "c1222.calling_authentication_value_c1221",
1810         FT_UINT32, BASE_DEC, VALS(c1222_Calling_authentication_value_c1221_U_vals), 0,
1811         NULL, HFILL }},
1812     { &hf_c1222_key_id_element,
1813       { "key-id-element", "c1222.key_id_element",
1814         FT_BYTES, BASE_NONE, NULL, 0,
1815         NULL, HFILL }},
1816     { &hf_c1222_iv_element,
1817       { "iv-element", "c1222.iv_element",
1818         FT_BYTES, BASE_NONE, NULL, 0,
1819         NULL, HFILL }},
1820     { &hf_c1222_c1221_auth_identification,
1821       { "c1221-auth-identification", "c1222.c1221_auth_identification",
1822         FT_BYTES, BASE_NONE, NULL, 0,
1823         "OCTET_STRING_SIZE_CONSTR001", HFILL }},
1824     { &hf_c1222_c1221_auth_request,
1825       { "c1221-auth-request", "c1222.c1221_auth_request",
1826         FT_BYTES, BASE_NONE, NULL, 0,
1827         "OCTET_STRING_SIZE_1_255", HFILL }},
1828     { &hf_c1222_c1221_auth_response,
1829       { "c1221-auth-response", "c1222.c1221_auth_response",
1830         FT_BYTES, BASE_NONE, NULL, 0,
1831         "OCTET_STRING_SIZE_CONSTR002", HFILL }},
1832
1833 /*--- End of included file: packet-c1222-hfarr.c ---*/
1834 #line 1273 "../../asn1/c1222/packet-c1222-template.c"
1835   };
1836
1837   /* List of subtrees */
1838   static gint *ett[] = {
1839                   &ett_c1222,
1840                   &ett_c1222_epsem,
1841                   &ett_c1222_flags,
1842                   &ett_c1222_crypto,
1843                   &ett_c1222_cmd,
1844
1845 /*--- Included file: packet-c1222-ettarr.c ---*/
1846 #line 1 "../../asn1/c1222/packet-c1222-ettarr.c"
1847     &ett_c1222_C1222_MESSAGE_U,
1848     &ett_c1222_Calling_authentication_value_U,
1849     &ett_c1222_Authentication_value_encoding,
1850     &ett_c1222_Calling_authentication_value_single_asn1,
1851     &ett_c1222_Calling_authentication_value_c1222_U,
1852     &ett_c1222_Calling_authentication_value_c1221_U,
1853
1854 /*--- End of included file: packet-c1222-ettarr.c ---*/
1855 #line 1283 "../../asn1/c1222/packet-c1222-template.c"
1856   };
1857
1858   module_t *c1222_module;
1859
1860 #ifdef HAVE_LIBGCRYPT
1861   static uat_field_t c1222_uat_flds[] = {
1862     UAT_FLD_HEX(c1222_users,keynum,"Key ID","Key identifier in hexadecimal"),
1863     UAT_FLD_BUFFER(c1222_users, key, "Key", "Encryption key as 16-byte hex string"),
1864     UAT_END_FIELDS
1865   };
1866 #endif /* HAVE_LIBGCRYPT */
1867
1868   /* Register protocol */
1869   proto_c1222 = proto_register_protocol(PNAME, PSNAME, PFNAME);
1870   /* Register fields and subtrees */
1871   proto_register_field_array(proto_c1222, hf, array_length(hf));
1872   proto_register_subtree_array(ett, array_length(ett));
1873   c1222_module = prefs_register_protocol(proto_c1222, proto_reg_handoff_c1222);
1874   prefs_register_bool_preference(c1222_module, "desegment",
1875         "Reassemble all C12.22 messages spanning multiple TCP segments",
1876         "Whether the C12.22 dissector should reassemble all messages spanning multiple TCP segments",
1877         &c1222_desegment);
1878 #ifdef HAVE_LIBGCRYPT
1879   prefs_register_bool_preference(c1222_module, "decrypt",
1880         "Verify crypto for all applicable C12.22 messages",
1881         "Whether the C12.22 dissector should verify the crypto for all relevant messages",
1882         &c1222_decrypt);
1883
1884   c1222_uat = uat_new("Decryption Table",
1885       sizeof(c1222_uat_data_t),         /* record size */
1886       "c1222_decryption_table",         /* filename */
1887       TRUE,                             /* from_profile */
1888       (void*)&c1222_uat_data,           /* data_ptr */
1889       &num_c1222_uat_data,              /* numitems_ptr */
1890       UAT_AFFECTS_DISSECTION,           /* affects dissection of packets, but not set of named fields */
1891       NULL,                             /* help */
1892       NULL,                             /* copy callback */
1893       c1222_uat_data_update_cb,         /* update callback */
1894       NULL,                             /* free callback */
1895       NULL,                             /* post update callback */
1896       c1222_uat_flds);                  /* UAT field definitions */
1897
1898   prefs_register_uat_preference(c1222_module,
1899       "decryption_table",
1900       "Decryption Table",
1901       "Table of security parameters for decryption of C12.22 packets",
1902       c1222_uat);
1903 #endif /* HAVE_LIBGCRYPT */
1904 }
1905
1906 /*--- proto_reg_handoff_c1222 ---------------------------------------*/
1907 void
1908 proto_reg_handoff_c1222(void)
1909 {
1910     static gboolean initialized = FALSE;
1911
1912     if( !initialized ) {
1913         c1222_handle = create_dissector_handle(dissect_c1222, proto_c1222);
1914         dissector_add_uint("tcp.port", global_c1222_port, c1222_handle);
1915         initialized = TRUE;
1916     }
1917 }