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