FIXUP: WIP: verification_trailer
[wireshark-wip.git] / epan / dissectors / packet-c1222.c
blobdf2b1117040e59c9ee60b37b17941939d8becf10
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 */
6 /* Input file: packet-c1222-template.c */
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.beroset@elster.com
13 * $Id$
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
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.
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.
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.
34 #include "config.h"
36 #include <glib.h>
38 #include <wsutil/eax.h>
40 #include <epan/conversation.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/oids.h>
50 #include <stdio.h>
51 #include <string.h>
53 #include "packet-c1222.h"
55 #define PNAME "ANSI C12.22"
56 #define PSNAME "C12.22"
57 #define PFNAME "c1222"
58 #define C1222_PORT 1153 /* TCP port */
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
68 /* if the packet is encrypted, it can be
69 * good, bad, or simply not checked
71 #define C1222_EPSEM_CRYPTO_GOOD 0x01
72 #define C1222_EPSEM_CRYPTO_BAD 0x02
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
92 static dissector_handle_t c1222_handle=NULL;
93 static dissector_handle_t c1222_udp_handle=NULL;
95 /* Initialize the protocol and registered fields */
96 static int proto_c1222 = -1;
97 static int global_c1222_port = C1222_PORT;
98 static gboolean c1222_desegment = TRUE;
99 static gboolean c1222_decrypt = TRUE;
100 static const gchar *c1222_baseoid_str = NULL;
101 static guint8 *c1222_baseoid = NULL;
102 static guint c1222_baseoid_len = 0;
105 /*--- Included file: packet-c1222-hf.c ---*/
106 #line 1 "../../asn1/c1222/packet-c1222-hf.c"
107 static int hf_c1222_MESSAGE_PDU = -1; /* MESSAGE */
108 static int hf_c1222_aSO_context = -1; /* ASO_qualifier */
109 static int hf_c1222_called_AP_title = -1; /* Called_AP_title */
110 static int hf_c1222_called_AP_invocation_id = -1; /* Called_AP_invocation_id */
111 static int hf_c1222_calling_AP_title = -1; /* Calling_AP_title */
112 static int hf_c1222_calling_AE_qualifier = -1; /* Calling_AE_qualifier */
113 static int hf_c1222_calling_AP_invocation_id = -1; /* Calling_AP_invocation_id */
114 static int hf_c1222_mechanism_name = -1; /* Mechanism_name */
115 static int hf_c1222_calling_authentication_value = -1; /* Calling_authentication_value */
116 static int hf_c1222_user_information = -1; /* User_information */
117 static int hf_c1222_called_ap_title_abs = -1; /* OBJECT_IDENTIFIER */
118 static int hf_c1222_called_ap_title_rel = -1; /* RELATIVE_OID */
119 static int hf_c1222_calling_ap_title_abs = -1; /* OBJECT_IDENTIFIER */
120 static int hf_c1222_calling_ap_title_rel = -1; /* RELATIVE_OID */
121 static int hf_c1222_calling_authentication_value_indirect = -1; /* INTEGER */
122 static int hf_c1222_calling_authentication_value_encoding = -1; /* Authentication_value_encoding */
123 static int hf_c1222_calling_authentication_value_single_asn1 = -1; /* Calling_authentication_value_single_asn1 */
124 static int hf_c1222_calling_authentication_value_octet_aligned = -1; /* OCTET_STRING */
125 static int hf_c1222_calling_authentication_value_c1222 = -1; /* Calling_authentication_value_c1222 */
126 static int hf_c1222_calling_authentication_value_c1221 = -1; /* Calling_authentication_value_c1221 */
127 static int hf_c1222_key_id_element = -1; /* Key_id_element */
128 static int hf_c1222_iv_element = -1; /* Iv_element */
129 static int hf_c1222_c1221_auth_identification = -1; /* OCTET_STRING_SIZE_CONSTR001 */
130 static int hf_c1222_c1221_auth_request = -1; /* OCTET_STRING_SIZE_1_255 */
131 static int hf_c1222_c1221_auth_response = -1; /* OCTET_STRING_SIZE_CONSTR002 */
133 /*--- End of included file: packet-c1222-hf.c ---*/
134 #line 97 "../../asn1/c1222/packet-c1222-template.c"
135 /* These are the EPSEM pieces */
136 /* first, the flag components */
137 static int hf_c1222_epsem_flags = -1;
138 static int hf_c1222_epsem_flags_reserved = -1;
139 static int hf_c1222_epsem_flags_recovery = -1;
140 static int hf_c1222_epsem_flags_proxy = -1;
141 static int hf_c1222_epsem_flags_ed_class = -1;
142 static int hf_c1222_epsem_flags_security_modes = -1;
143 static int hf_c1222_epsem_flags_response_control = -1;
144 /* and the structure of the flag components */
145 static const int *c1222_flags[] = {
146 &hf_c1222_epsem_flags_reserved,
147 &hf_c1222_epsem_flags_recovery,
148 &hf_c1222_epsem_flags_proxy,
149 &hf_c1222_epsem_flags_ed_class,
150 &hf_c1222_epsem_flags_security_modes,
151 &hf_c1222_epsem_flags_response_control,
152 NULL
154 /* next the optional ed_class */
155 static int hf_c1222_epsem_ed_class = -1;
156 /* now the aggregate epsem */
157 static int hf_c1222_epsem_total = -1;
158 /* generic command */
159 static int hf_c1222_cmd = -1;
160 static int hf_c1222_err = -1;
161 static int hf_c1222_data = -1;
162 /* individual epsem fields */
163 static int hf_c1222_logon_id = -1;
164 static int hf_c1222_logon_user = -1;
165 static int hf_c1222_security_password = -1;
166 static int hf_c1222_auth_len = -1;
167 static int hf_c1222_auth_data = -1;
168 static int hf_c1222_read_table = -1;
169 static int hf_c1222_read_offset = -1;
170 static int hf_c1222_read_count = -1;
171 static int hf_c1222_write_table = -1;
172 static int hf_c1222_write_offset = -1;
173 static int hf_c1222_write_size = -1;
174 static int hf_c1222_write_data = -1;
175 static int hf_c1222_procedure_num = -1;
176 static int hf_c1222_write_chksum = -1;
177 static int hf_c1222_wait_secs = -1;
178 static int hf_c1222_neg_pkt_size = -1;
179 static int hf_c1222_neg_nbr_pkts = -1;
180 static int hf_c1222_timing_setup_traffic = -1;
181 static int hf_c1222_timing_setup_inter_char = -1;
182 static int hf_c1222_timing_setup_resp_to = -1;
183 static int hf_c1222_timing_setup_nbr_retries = -1;
185 /* the MAC */
186 static int hf_c1222_epsem_mac = -1;
188 /* crypto result flags */
189 static int hf_c1222_epsem_crypto_good = -1;
190 static int hf_c1222_epsem_crypto_bad = -1;
192 /* Initialize the subtree pointers */
193 static int ett_c1222 = -1;
194 static int ett_c1222_epsem = -1;
195 static int ett_c1222_flags = -1;
196 static int ett_c1222_crypto = -1;
197 static int ett_c1222_cmd = -1;
199 #ifdef HAVE_LIBGCRYPT
200 /* these pointers are for the header elements that may be needed to verify the crypto */
201 static guint8 *aSO_context = NULL;
202 static guint8 *called_AP_title = NULL;
203 static guint8 *called_AP_invocation_id = NULL;
204 static guint8 *calling_AE_qualifier = NULL;
205 static guint8 *calling_AP_invocation_id = NULL;
206 static guint8 *mechanism_name = NULL;
207 static guint8 *calling_authentication_value = NULL;
208 static guint8 *user_information = NULL;
209 static guint8 *calling_AP_title = NULL;
210 static guint8 *key_id_element = NULL;
211 static guint8 *iv_element = NULL;
213 /* these are the related lengths */
214 static guint32 aSO_context_len = 0;
215 static guint32 called_AP_title_len = 0;
216 static guint32 called_AP_invocation_id_len = 0;
217 static guint32 calling_AE_qualifier_len = 0;
218 static guint32 calling_AP_invocation_id_len = 0;
219 static guint32 mechanism_name_len = 0;
220 static guint32 calling_authentication_value_len = 0;
221 static guint32 user_information_len = 0;
222 static guint32 calling_AP_title_len = 0;
223 static guint32 key_id_element_len = 0;
224 static guint32 iv_element_len = 0;
225 #endif /* HAVE_LIBGCRYPT */
228 /*--- Included file: packet-c1222-ett.c ---*/
229 #line 1 "../../asn1/c1222/packet-c1222-ett.c"
230 static gint ett_c1222_MESSAGE_U = -1;
231 static gint ett_c1222_Called_AP_title = -1;
232 static gint ett_c1222_Calling_AP_title = -1;
233 static gint ett_c1222_Calling_authentication_value_U = -1;
234 static gint ett_c1222_Authentication_value_encoding = -1;
235 static gint ett_c1222_Calling_authentication_value_single_asn1 = -1;
236 static gint ett_c1222_Calling_authentication_value_c1222_U = -1;
237 static gint ett_c1222_Calling_authentication_value_c1221_U = -1;
239 /*--- End of included file: packet-c1222-ett.c ---*/
240 #line 190 "../../asn1/c1222/packet-c1222-template.c"
242 static expert_field ei_c1222_command_truncated = EI_INIT;
243 static expert_field ei_c1222_bad_checksum = EI_INIT;
244 static expert_field ei_c1222_epsem_missing = EI_INIT;
245 #ifdef HAVE_LIBGCRYPT
246 static expert_field ei_c1222_epsem_failed_authentication = EI_INIT;
247 #else
248 static expert_field ei_c1222_epsem_not_authenticated = EI_INIT;
249 #endif
250 static expert_field ei_c1222_epsem_not_decryped = EI_INIT;
251 static expert_field ei_c1222_ed_class_missing = EI_INIT;
252 static expert_field ei_c1222_epsem_ber_length_error = EI_INIT;
253 static expert_field ei_c1222_epsem_field_length_error = EI_INIT;
254 static expert_field ei_c1222_mac_missing = EI_INIT;
256 /*------------------------------
257 * Data Structures
258 *------------------------------
260 typedef struct _c1222_uat_data {
261 guint keynum;
262 guchar *key;
263 guint keylen;
264 } c1222_uat_data_t;
266 static const value_string c1222_security_modes[] = {
267 { 0x00, "Cleartext"},
268 { 0x01, "Cleartext with authentication"},
269 { 0x02, "Ciphertext with authentication"},
270 { 0, NULL }
273 static const value_string c1222_response_control[] = {
274 { 0x00, "Always respond"},
275 { 0x01, "Respond on exception"},
276 { 0x02, "Never respond"},
277 { 0, NULL }
280 static const value_string tableflags[] = {
281 { 0x00, "ST" },
282 { 0x08, "MT" },
283 { 0x10, "Pending ST" },
284 { 0x18, "Pending MT" },
285 { 0, NULL }
288 static const value_string procflags[] = {
289 { 0x00, "SF" },
290 { 0x08, "MF" },
291 { 0, NULL }
294 static const value_string commandnames[] = {
295 /* error codes are in the range 0x00 - 0x1f inclusive */
296 { 0x00, "OK" },
297 { 0x01, "Error" },
298 { 0x02, "Service Not Supported" },
299 { 0x03, "Insufficient Security Clearance" },
300 { 0x04, "Operation Not Possible" },
301 { 0x05, "Inappropriate Action Requested" },
302 { 0x06, "Device Busy" },
303 { 0x07, "Data Not Ready" },
304 { 0x08, "Data Locked" },
305 { 0x09, "Renegotiate Request" },
306 { 0x0A, "Invalid Service Sequence State" },
307 { 0x0B, "Security Mechanism Error" },
308 { 0x0C, "Unknown Application Title" },
309 { 0x0D, "Network Time-out" },
310 { 0x0E, "Network Not Reachable" },
311 { 0x0F, "Request Too Large" },
312 { 0x10, "Response Too Large" },
313 { 0x11, "Segmentation Not Possible" },
314 { 0x12, "Segmentation Error" },
315 /* commands are in the range 0x20 - 0x7f inclusive */
316 {C1222_CMD_IDENTIFY, "Identify" },
317 {C1222_CMD_TERMINATE, "Terminate" },
318 {C1222_CMD_DISCONNECT, "Disconnect" },
319 {C1222_CMD_FULL_READ, "Full Read" },
320 {C1222_CMD_DEFAULT_READ, "Default Read" },
321 {C1222_CMD_PARTIAL_READ_OFFSET, "Partial Read Offset" },
322 {C1222_CMD_FULL_WRITE, "Full Write" },
323 {C1222_CMD_DEFAULT_WRITE, "Default Write" },
324 {C1222_CMD_PARTIAL_WRITE_OFFSET, "Partial Write Offset" },
325 {C1222_CMD_LOGON, "Logon" },
326 {C1222_CMD_SECURITY, "Security" },
327 {C1222_CMD_LOGOFF, "Logoff" },
328 {C1222_CMD_AUTHENTICATE, "Authenticate" },
329 {C1222_CMD_NEGOTIATE, "Negotiate" },
330 {C1222_CMD_NEGOTIATE | 0x1, "Negotiate w/ 1 Baud Rate" },
331 {C1222_CMD_NEGOTIATE | 0x2, "Negotiate w/ 2 Baud Rates" },
332 {C1222_CMD_NEGOTIATE | 0x3, "Negotiate w/ 3 Baud Rates" },
333 {C1222_CMD_NEGOTIATE | 0x4, "Negotiate w/ 4 Baud Rates" },
334 {C1222_CMD_NEGOTIATE | 0x5, "Negotiate w/ 5 Baud Rates" },
335 {C1222_CMD_NEGOTIATE | 0x6, "Negotiate w/ 6 Baud Rates" },
336 {C1222_CMD_NEGOTIATE | 0x7, "Negotiate w/ 7 Baud Rates" },
337 {C1222_CMD_NEGOTIATE | 0x8, "Negotiate w/ 8 Baud Rates" },
338 {C1222_CMD_NEGOTIATE | 0x9, "Negotiate w/ 9 Baud Rates" },
339 {C1222_CMD_NEGOTIATE | 0xA, "Negotiate w/ 10 Baud Rates" },
340 {C1222_CMD_NEGOTIATE | 0xB, "Negotiate w/ 11 Baud Rates" },
341 {C1222_CMD_WAIT, "Wait" },
342 {C1222_CMD_TIMING_SETUP, "Timing Setup" },
343 { 0, NULL }
346 #ifdef HAVE_LIBGCRYPT
347 /* these are for the key tables */
348 UAT_HEX_CB_DEF(c1222_users, keynum, c1222_uat_data_t)
349 UAT_BUFFER_CB_DEF(c1222_users, key, c1222_uat_data_t, key, keylen)
351 static c1222_uat_data_t *c1222_uat_data = NULL;
352 static guint num_c1222_uat_data = 0;
353 static uat_t *c1222_uat;
355 /* these macros ares used to populate fields needed to verify crypto */
356 #define FILL_START int length, start_offset = offset;
357 #define FILL_TABLE(fieldname) \
358 length = offset - start_offset; \
359 fieldname = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start_offset, length); \
360 fieldname##_len = length;
361 #define FILL_TABLE_TRUNCATE(fieldname, len) \
362 length = 1 + 2*(offset - start_offset); \
363 fieldname = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start_offset, length); \
364 fieldname##_len = len;
365 #define FILL_TABLE_APTITLE(fieldname) \
366 length = offset - start_offset; \
367 switch (tvb_get_guint8(tvb, start_offset)) { \
368 case 0x80: /* relative OID */ \
369 tvb_ensure_bytes_exist(tvb, start_offset, length); \
370 fieldname##_len = length + c1222_baseoid_len; \
371 fieldname = (guint8 *)wmem_alloc(wmem_packet_scope(), fieldname##_len); \
372 fieldname[0] = 0x06; /* create absolute OID tag */ \
373 fieldname[1] = (fieldname##_len - 2) & 0xff; \
374 memcpy(&(fieldname[2]), c1222_baseoid, c1222_baseoid_len); \
375 tvb_memcpy(tvb, &(fieldname[c1222_baseoid_len+2]), start_offset+2, length-2); \
376 break; \
377 case 0x06: /* absolute OID */ \
378 default: \
379 fieldname = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, start_offset, length); \
380 fieldname##_len = length; \
381 break; \
383 #else /* HAVE_LIBGCRYPT */
384 #define FILL_TABLE(fieldname)
385 #define FILL_TABLE_TRUNCATE(fieldname, len)
386 #define FILL_TABLE_APTITLE(fieldname)
387 #define FILL_START
388 #endif /* HAVE_LIBGCRYPT */
390 /*------------------------------
391 * Function Prototypes
392 *------------------------------
394 void proto_reg_handoff_c1222(void);
397 /*------------------------------
398 * Code
399 *------------------------------
403 * Calculates simple one's complement checksum.
405 * \param tvb pointer to tvbuff containing data to be checksummed
406 * \param offset offset within tvbuff to beginning of data
407 * \param len length of data to be checksummed
408 * \returns calculated checksum
410 static guint8
411 c1222_cksum(tvbuff_t *tvb, gint offset, int len)
413 guint8 sum;
414 for (sum = 0; len; offset++, len--)
415 sum += tvb_get_guint8(tvb, offset);
416 return ~sum + 1;
419 * Dissects C12.22 packet in detail (with a tree).
421 * \param tvb input buffer containing packet to be dissected
422 * \param pinfo the packet info of the current data
423 * \param tree the tree to append this item to
424 * \param length length of data
425 * \param offset the offset in the tvb
427 static void
428 parse_c1222_detailed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int cmd, guint32 *length, int *offset)
430 guint16 user_id = 0;
431 guint8 *user_name = NULL;
432 guint8 *password = NULL;
433 guint8 auth_len = 0;
434 gchar *auth_req = NULL;
435 guint16 table = 0;
436 guint16 tblsize = 0;
437 guint8 chksum = 0;
438 guint16 calcsum = 0;
439 guint8 wait_seconds = 0;
440 int numrates = 0;
441 guint16 packet_size;
442 guint16 procedure_num = 0;
443 guint8 nbr_packet;
444 /* timing setup parameters */
445 guint8 traffic;
446 guint8 inter_char;
447 guint8 resp_to;
448 guint8 nbr_retries;
449 proto_item *item = NULL;
451 /* special case to simplify handling of Negotiate service */
452 if ((cmd & 0xF0) == C1222_CMD_NEGOTIATE) {
453 numrates = cmd & 0x0F;
454 cmd = C1222_CMD_NEGOTIATE;
456 proto_tree_add_uint(tree, cmd >= 0x20 ? hf_c1222_cmd : hf_c1222_err, tvb, *offset, 1, cmd);
457 (*offset)++;
458 (*length)--;
459 switch (cmd) {
460 case C1222_CMD_LOGON:
461 if (*length >= 12) {
462 user_id = tvb_get_ntohs(tvb, *offset);
463 proto_tree_add_uint(tree, hf_c1222_logon_id, tvb, *offset, 2, user_id);
464 *offset += 2;
465 user_name = tvb_get_string(wmem_packet_scope(),tvb, *offset, 10);
466 proto_tree_add_string(tree, hf_c1222_logon_user, tvb, *offset, 10, user_name);
467 *offset += 10;
468 *length -= 12;
469 proto_item_set_text(tree, "C12.22 EPSEM: %s (id %d, user \"%s\")",
470 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), user_id, user_name);
471 } else {
472 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 LOGON command truncated");
474 break;
475 case C1222_CMD_SECURITY:
476 if (*length >= 20) {
477 password = tvb_get_string(wmem_packet_scope(),tvb, *offset, 20);
478 proto_tree_add_string(tree, hf_c1222_security_password, tvb, *offset, 20, password);
479 *offset += 20;
480 *length -= 20;
481 if (*length >= 2) {
482 user_id = tvb_get_ntohs(tvb, *offset);
483 proto_tree_add_uint(tree, hf_c1222_logon_id, tvb, *offset, 2, user_id);
484 *offset += 2;
485 *length -= 2;
486 proto_item_set_text(tree, "C12.22 EPSEM: %s (password \"%s\", id %d)",
487 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), password, user_id);
488 } else {
489 proto_item_set_text(tree, "C12.22 EPSEM: %s (password \"%s\")",
490 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), password);
492 } else {
493 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 SECURITY command truncated");
495 break;
496 case C1222_CMD_AUTHENTICATE:
497 if (*length >= 1) {
498 auth_len = tvb_get_guint8(tvb, *offset);
499 proto_tree_add_uint(tree, hf_c1222_auth_len, tvb, *offset, 1, auth_len);
500 *offset += 1;
501 if (*length >= auth_len) {
502 auth_req = tvb_bytes_to_str(tvb, *offset, auth_len);
503 proto_tree_add_item(tree, hf_c1222_auth_data, tvb, *offset, auth_len, ENC_NA);
504 *offset += auth_len;
505 *length -= auth_len + 1;
506 proto_item_set_text(tree, "C12.22 EPSEM: %s (%d bytes: %s)",
507 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), auth_len, auth_req);
508 } else {
509 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 AUTHENTICATE command truncated");
511 } else {
512 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 AUTHENTICATE command truncated");
514 break;
515 case C1222_CMD_FULL_READ:
516 if (*length >= 2) {
517 table = tvb_get_ntohs(tvb, *offset);
518 proto_tree_add_uint(tree, hf_c1222_read_table, tvb, *offset, 2, table);
519 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
520 val_to_str(cmd,commandnames,"Unknown (0x%02x)"),
521 val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
522 *offset += 2;
523 *length -= 2;
524 } else {
525 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 READ command truncated");
527 break;
528 case C1222_CMD_PARTIAL_READ_OFFSET:
529 if (*length >= 7) {
530 table = tvb_get_ntohs(tvb, *offset);
531 proto_tree_add_uint(tree, hf_c1222_read_table, tvb, *offset, 2, table);
532 *offset += 2;
533 *length -= 2;
534 proto_tree_add_item(tree, hf_c1222_read_offset, tvb, *offset, 3, ENC_BIG_ENDIAN);
535 *offset += 3;
536 *length -= 3;
537 proto_tree_add_item(tree, hf_c1222_read_count, tvb, *offset, 2, ENC_BIG_ENDIAN);
538 *offset += 2;
539 *length -= 2;
540 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
541 val_to_str(cmd,commandnames,"Unknown (0x%02x)"),
542 val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
543 } else {
544 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 READ command truncated");
546 break;
547 case C1222_CMD_FULL_WRITE:
548 if (*length >= 5) {
549 table = tvb_get_ntohs(tvb, *offset);
550 proto_tree_add_uint(tree, hf_c1222_write_table, tvb, *offset, 2, table);
551 *offset += 2;
552 *length -= 2;
553 tblsize = tvb_get_ntohs(tvb, *offset);
554 proto_tree_add_uint(tree, hf_c1222_write_size, tvb, *offset, 2, tblsize);
555 *offset += 2;
556 *length -= 2;
557 if (*length >= tblsize+1U) {
558 if (table == 7) {/* is it a procedure call? */
559 procedure_num = tvb_get_letohs(tvb, *offset);
560 proto_tree_add_uint(tree, hf_c1222_procedure_num, tvb, *offset, 2, procedure_num);
561 *offset += 2;
562 *length -= 2;
563 tblsize -= 2;
565 proto_tree_add_item(tree, hf_c1222_write_data, tvb, *offset, tblsize, ENC_NA);
566 *offset += tblsize;
567 *length -= tblsize;
568 chksum = tvb_get_guint8(tvb, *offset);
569 item = proto_tree_add_uint(tree, hf_c1222_write_chksum, tvb, *offset, 1, chksum);
570 if (table == 7) {/* is it a procedure call? */
571 calcsum = c1222_cksum(tvb, (*offset)-tblsize-2, tblsize+2);
572 } else {
573 calcsum = c1222_cksum(tvb, (*offset)-tblsize, tblsize);
575 if (chksum != calcsum) {
576 expert_add_info_format(pinfo, item, &ei_c1222_bad_checksum, "Bad checksum [should be 0x%02x]", calcsum);
578 if (table == 7) {/* is it a procedure call? */
579 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d, %s-%d)",
580 val_to_str(cmd,commandnames,"Unknown (0x%02x)"),
581 val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF,
582 val_to_str((procedure_num >> 8) & 0xF8, procflags,"Unknown (0x%04x)"), procedure_num & 0x7FF);
583 } else {
584 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
585 val_to_str(cmd,commandnames,"Unknown (0x%02x)"),
586 val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
588 *offset += 1;
589 *length -= 1;
590 } else {
591 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 WRITE command truncated");
593 } else {
594 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 WRITE command truncated");
596 break;
597 case C1222_CMD_PARTIAL_WRITE_OFFSET:
598 if (*length >= 8) {
599 table = tvb_get_ntohs(tvb, *offset);
600 proto_tree_add_uint(tree, hf_c1222_write_table, tvb, *offset, 2, table);
601 *offset += 2;
602 *length -= 2;
603 proto_tree_add_item(tree, hf_c1222_write_offset, tvb, *offset, 3, ENC_BIG_ENDIAN);
604 *offset += 3;
605 *length -= 3;
606 tblsize = tvb_get_ntohs(tvb, *offset);
607 proto_tree_add_uint(tree, hf_c1222_write_size, tvb, *offset, 2, tblsize);
608 *offset += 2;
609 *length -= 2;
610 if (*length >= tblsize+1U) {
611 proto_tree_add_item(tree, hf_c1222_write_data, tvb, *offset, tblsize, ENC_NA);
612 *offset += tblsize;
613 *length -= tblsize;
614 chksum = tvb_get_guint8(tvb, *offset);
615 item = proto_tree_add_uint(tree, hf_c1222_write_chksum, tvb, *offset, 1, chksum);
616 calcsum = c1222_cksum(tvb, (*offset)-tblsize, tblsize);
617 if (chksum != calcsum) {
618 expert_add_info_format(pinfo, item, &ei_c1222_bad_checksum, "Bad checksum [should be 0x%02x]", calcsum);
620 proto_item_set_text(tree, "C12.22 EPSEM: %s (%s-%d)",
621 val_to_str(cmd,commandnames,"Unknown (0x%02x)"),
622 val_to_str((table >> 8) & 0xF8, tableflags,"Unknown (0x%04x)"), table & 0x7FF);
623 *offset += 1;
624 *length -= 1;
625 } else {
626 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 WRITE command truncated");
628 } else {
629 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 WRITE command truncated");
631 break;
632 case C1222_CMD_WAIT:
633 if (*length >= 1) {
634 wait_seconds = tvb_get_guint8(tvb, *offset);
635 proto_tree_add_uint(tree, hf_c1222_wait_secs, tvb, *offset, 1, wait_seconds);
636 *offset += 1;
637 *length -= 1;
638 proto_item_set_text(tree, "C12.22 EPSEM: %s (%d seconds)",
639 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), wait_seconds);
640 } else {
641 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 WAIT command truncated");
643 break;
644 case C1222_CMD_NEGOTIATE:
645 if (*length >= 3) {
646 packet_size = tvb_get_ntohs(tvb, *offset);
647 proto_tree_add_uint(tree, hf_c1222_neg_pkt_size, tvb, *offset, 2, packet_size);
648 *offset += 2;
649 *length -= 2;
650 nbr_packet = tvb_get_guint8(tvb, *offset);
651 proto_tree_add_uint(tree, hf_c1222_neg_nbr_pkts, tvb, *offset, 1, nbr_packet);
652 *offset += 1;
653 *length -= 1;
654 proto_item_set_text(tree, "C12.22 EPSEM: %s (pkt size %d, num pkts %d, with %d baud rates)",
655 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), packet_size, nbr_packet, numrates);
656 } else {
657 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 NEGOTIATE command truncated");
659 break;
660 case C1222_CMD_TIMING_SETUP:
661 if (*length >= 4) {
662 traffic = tvb_get_guint8(tvb, *offset);
663 proto_tree_add_uint(tree, hf_c1222_timing_setup_traffic, tvb, *offset, 1, traffic);
664 *offset += 1;
665 *length -= 1;
666 inter_char = tvb_get_guint8(tvb, *offset);
667 proto_tree_add_uint(tree, hf_c1222_timing_setup_inter_char, tvb, *offset, 1, inter_char);
668 *offset += 1;
669 *length -= 1;
670 resp_to = tvb_get_guint8(tvb, *offset);
671 proto_tree_add_uint(tree, hf_c1222_timing_setup_resp_to, tvb, *offset, 1, resp_to);
672 *offset += 1;
673 *length -= 1;
674 nbr_retries = tvb_get_guint8(tvb, *offset);
675 proto_tree_add_uint(tree, hf_c1222_timing_setup_nbr_retries, tvb, *offset, 1, nbr_retries);
676 *offset += 1;
677 *length -= 1;
678 proto_item_set_text(tree, "C12.22 EPSEM: %s (traffic to %d s, inter-char to %d s, response to %d s, %d retries)",
679 val_to_str(cmd,commandnames,"Unknown (0x%02x)"), traffic, inter_char, resp_to, nbr_retries);
680 } else {
681 expert_add_info_format(pinfo, tree, &ei_c1222_command_truncated, "C12.22 NEGOTIATE command truncated");
683 break;
685 default:
686 /* don't do anything */
687 proto_item_set_text(tree, "C12.22 EPSEM: %s", val_to_str(cmd, commandnames, "Unknown (0x%02x)"));
688 if (*length) {
689 proto_tree_add_item(tree, hf_c1222_data, tvb, *offset, *length, ENC_NA);
691 break;
695 #ifdef HAVE_LIBGCRYPT
696 typedef struct tagTOP_ELEMENT_CONTROL
698 /* TRUE if this tag is required */
699 gboolean required;
700 /* TRUE if we must truncate this tag */
701 gboolean truncate;
702 /* actual hex value of the tag we're seeking */
703 guint8 tag;
704 /* if TRUE, add tag and length before copying */
705 gboolean addtag;
706 /* pointer to pointer to memory copy of element */
707 guint8 **element;
708 /* pointer to element length */
709 guint32 *length;
710 } TOP_ELEMENT_CONTROL;
712 static const TOP_ELEMENT_CONTROL canonifyTable[] = {
713 { FALSE, FALSE, 0xA1, TRUE, &aSO_context, &aSO_context_len },
714 { TRUE , FALSE, 0xA2, TRUE, &called_AP_title, &called_AP_title_len },
715 { FALSE, FALSE, 0xA4, TRUE, &called_AP_invocation_id, &called_AP_invocation_id_len },
716 { FALSE, FALSE, 0xA7, TRUE, &calling_AE_qualifier, &calling_AE_qualifier_len },
717 { TRUE, FALSE, 0xA8, TRUE, &calling_AP_invocation_id, &calling_AP_invocation_id_len },
718 { FALSE, FALSE, 0x8B, TRUE, &mechanism_name, &mechanism_name_len },
719 { FALSE, FALSE, 0xAC, TRUE, &calling_authentication_value, &calling_authentication_value_len },
720 { TRUE , TRUE , 0xBE, TRUE, &user_information, &user_information_len },
721 { FALSE, FALSE, 0xA6, TRUE, &calling_AP_title, &calling_AP_title_len },
722 { FALSE, FALSE, 0xAC, FALSE, &key_id_element, &key_id_element_len },
723 { FALSE, FALSE, 0xAC, FALSE, &iv_element, &iv_element_len },
724 { FALSE, FALSE, 0x0, TRUE, NULL, NULL }
727 static void
728 clear_canon(void)
730 const TOP_ELEMENT_CONTROL *t = canonifyTable;
732 for (t = canonifyTable; t->element != NULL; t++) {
733 *(t->length) = 0;
734 *(t->element) = NULL;
739 * Calculates the size of the passed number n as encoded as a BER length field.
741 * \param n is the length value to be BER encoded
742 * \returns the sized of the encoding
744 static guint32
745 get_ber_len_size(guint32 n)
747 guint32 len = 1;
748 if (n > 0x7f) len++;
749 if (n > 0xff) len++;
750 if (n > 0xffff) len++;
751 if (n > 0xffffff) len++;
752 return len;
755 * Encodes the passed value n as a BER-encoded length at puts it in memory.
757 * \param ptr points to the buffer to be written
758 * \param n is the length to be BER encoded
759 * \maxsize is the maximum number of bytes we're allowed to write
760 * \returns length of encoded value in bytes
762 static int
763 encode_ber_len(guint8 *ptr, guint32 n, int maxsize)
765 int len = get_ber_len_size(n);
766 if (len > maxsize) return 0;
767 if (len == 1) {
768 *ptr = 0x7f & n;
769 } else {
770 *ptr = (len -1) | 0x80;
771 for (ptr += len-1; n; n >>= 8)
772 *ptr-- = n & 0xff;
774 return len;
779 * Checks a new encryption table item for validity.
781 * \param n points to the new record
782 * \param err is updated to point to an error string if needed
784 static void
785 c1222_uat_data_update_cb(void* n, const char** err)
787 c1222_uat_data_t* new_rec = (c1222_uat_data_t *)n;
789 if (new_rec->keynum > 0xff) {
790 *err = g_strdup("Invalid key number; must be less than 256");
792 if (new_rec->keylen != EAX_SIZEOF_KEY) {
793 *err = g_strdup("Invalid key size; must be 16 bytes");
798 * Canonifies header fields in preparation for authenticating and/or decrypting the packet.
800 * \param buff points to the allocated canonization buffer
801 * \param offset points to start of unallocated space in buffer and
802 is updated as we put bytes into buffer
803 * \param buffsize total size of allocated buffer
804 * \return FALSE if element is required and not present; otherwise TRUE
806 static gboolean
807 canonify_unencrypted_header(guchar *buff, guint32 *offset, guint32 buffsize)
809 const TOP_ELEMENT_CONTROL *t = canonifyTable;
810 guint32 len;
812 for (t = canonifyTable; t->element != NULL; t++)
814 len = *(t->length);
815 if (t->required && *(t->element) == NULL)
816 return FALSE;
817 if (*(t->element) != NULL) {
818 if (t->addtag) {
819 /* recreate original tag and length */
820 buff[(*offset)++] = t->tag;
821 (*offset) += encode_ber_len(&buff[*offset], len, 4);
823 if (t->truncate) {
824 len = 3+2*get_ber_len_size(len);
826 /* bail out if the cannonization buffer is too small */
827 /* this should never happen! */
828 if (buffsize < *offset + len) {
829 return FALSE;
831 memcpy(&buff[*offset], *(t->element), len);
832 (*offset) += len;
833 if (t->addtag) {
834 *(t->element) = NULL;
838 return TRUE;
842 * Looks up the required key in the key table.
844 * \param keybuff is updated with a copy of the key data if successful lookup.
845 * \param keyid is the ID number of the desired key
846 * \returns TRUE if key was found; otherwise FALSE
848 static gboolean
849 keylookup(guint8 *keybuff, guint8 keyid)
851 guint i;
853 if (c1222_uat_data == NULL)
854 return FALSE;
855 for (i = 0; i < num_c1222_uat_data; i++) {
856 if (c1222_uat_data[i].keynum == keyid) {
857 memcpy(keybuff, c1222_uat_data[i].key, EAX_SIZEOF_KEY);
858 return TRUE;
861 return FALSE;
865 * Authenticates and decrypts the passed packet.
867 * \param buffer points to a memory copy of the packet to be authenticated/decrypted
868 * and contains the decrypted value on successful return.
869 * \param length lenth of input packet
870 * \param decrypt TRUE if packet is to be authenticated and decrypted; FALSE if authentication only is requested
871 * \returns TRUE if the requested operation was successful; otherwise FALSE
873 static gboolean
874 decrypt_packet(guchar *buffer, guint32 length, gboolean decrypt)
876 #define CANONBUFFSIZE 300U
877 guchar canonbuff[CANONBUFFSIZE];
878 guint8 c1222_key[EAX_SIZEOF_KEY];
879 guchar key_id = 0;
880 guint32 offset = 0;
881 gboolean status = FALSE;
883 /* must be at least 4 bytes long to include the MAC */
884 if (length < 4)
885 return status;
886 if (key_id_element != NULL)
887 key_id = key_id_element[0];
888 /* extract unencrypted header information */
889 if (!canonify_unencrypted_header(canonbuff, &offset, CANONBUFFSIZE))
890 return status;
891 /* decrypt and authenticate in place */
892 /* PARAMETERS: pN : Pointer to ClearText (Input, Canonified form). */
893 /* pK : Pointer to secret key (Input). */
894 /* pC : Pointer to CipherText (Input/Output). */
895 /* SizeN : Byte length of ClearText buffer. */
896 /* SizeK : Byte length of secret key. */
897 /* SizeC : Byte length of CipherText buffer. */
898 /* pMac : Four byte Message Authentication Code. */
899 /* Mode : Operating mode (See EAX_MODE_xxx). */
900 /* RETURNS: TRUE if message has been authenticated. */
901 /* FALSE if not authenticated, invalid Mode, or error. */
902 if (offset) {
903 if (!keylookup((guint8 *)&c1222_key, key_id))
904 return FALSE;
905 status = Eax_Decrypt(canonbuff, c1222_key, buffer,
906 offset, EAX_SIZEOF_KEY, length-4,
907 (MAC_T *)&buffer[length-4],
908 decrypt ? EAX_MODE_CIPHERTEXT_AUTH : EAX_MODE_CLEARTEXT_AUTH);
910 return status;
912 #else /* HAVE_LIBCRYPT */
913 static gboolean
914 decrypt_packet(guchar *buffer _U_, guint32 length _U_, gboolean decrypt _U_)
916 return FALSE;
918 #endif /* HAVE_LIBGCRYPT */
921 * Checks to make sure that a complete, valid BER-encoded length is in the buffer.
923 * \param tvb contains the buffer to be examined
924 * \param offset is the offset within the buffer at which the BER-encded length begins
925 * \returns TRUE if a complete, valid BER-encoded length is in the buffer; otherwise FALSE
927 static gboolean
928 ber_len_ok(tvbuff_t *tvb, int offset)
930 guint8 ch;
932 if (tvb_offset_exists(tvb, offset)) {
933 ch = tvb_get_guint8(tvb, offset);
934 offset++;
935 if (!(ch & 0x80)) {
936 return TRUE;
937 } else if (tvb_offset_exists(tvb, offset)) {
938 ch = tvb_get_guint8(tvb, offset);
939 offset++;
940 if (!(ch & 0x80)) {
941 return TRUE;
942 } else if (tvb_offset_exists(tvb, offset)) {
943 ch = tvb_get_guint8(tvb, offset);
944 offset++;
945 if (!(ch & 0x80)) {
946 return TRUE;
947 } else if (tvb_offset_exists(tvb, offset)) {
948 ch = tvb_get_guint8(tvb, offset);
949 /*offset++;*/
950 if (!(ch & 0x80)) {
951 return TRUE;
957 return FALSE;
961 * Dissects the EPSEM portion of the User-information part of a C12.22 message.
963 * \param tvb the tv buffer of the current data
964 * \param offset the offset in the tvb
965 * \param len length of data
966 * \param pinfo the packet info of the current data
967 * \param tree the tree to append this item to
969 static int
970 dissect_epsem(tvbuff_t *tvb, int offset, guint32 len, packet_info *pinfo, proto_tree *tree)
972 proto_tree *cmd_tree = NULL;
973 proto_tree *ct = NULL;
974 proto_tree *crypto_tree = NULL;
975 proto_tree *yt = NULL;
976 proto_item *item = NULL;
977 guint8 flags;
978 int local_offset;
979 gint len2;
980 int cmd_err;
981 gboolean ind;
982 guchar *buffer;
983 tvbuff_t *epsem_buffer = NULL;
984 gboolean crypto_good = FALSE;
985 gboolean crypto_bad = FALSE;
986 gboolean hasmac = FALSE;
987 gboolean encrypted = FALSE;
989 if ((tvb == NULL) && (len == 0)) {
990 expert_add_info(pinfo, tree, &ei_c1222_epsem_missing);
991 return offset;
993 /* parse the flags byte which is always unencrypted */
994 flags = tvb_get_guint8(tvb, offset);
995 proto_tree_add_bitmask(tree, tvb, offset, hf_c1222_epsem_flags, ett_c1222_flags, c1222_flags, ENC_BIG_ENDIAN);
996 offset++;
997 switch ((flags & C1222_EPSEM_FLAG_SECURITY_MODE) >> 2) {
998 case EAX_MODE_CIPHERTEXT_AUTH:
999 /* mode is ciphertext with authentication */
1000 hasmac = TRUE;
1001 len2 = tvb_length_remaining(tvb, offset);
1002 if (len2 <= 0)
1003 return offset;
1004 encrypted = TRUE;
1005 if (c1222_decrypt) {
1006 buffer = (guchar *)tvb_memdup(wmem_packet_scope(), tvb, offset, len2);
1007 if (!decrypt_packet(buffer, len2, TRUE)) {
1008 crypto_bad = TRUE;
1009 } else {
1010 epsem_buffer = tvb_new_real_data(buffer, len2, len2);
1011 tvb_set_child_real_data_tvbuff(tvb, epsem_buffer);
1012 add_new_data_source(pinfo, epsem_buffer, "Decrypted EPSEM Data");
1013 crypto_good = TRUE;
1014 encrypted = FALSE;
1017 break;
1018 case EAX_MODE_CLEARTEXT_AUTH:
1019 /* mode is cleartext with authentication */
1020 hasmac = TRUE;
1021 len2 = tvb_length_remaining(tvb, offset);
1022 if (len2 <= 0)
1023 return offset;
1024 buffer = (guchar *)tvb_memdup(wmem_packet_scope(), tvb, offset, len2);
1025 epsem_buffer = tvb_new_subset_remaining(tvb, offset);
1026 if (c1222_decrypt) {
1027 if (!decrypt_packet(buffer, len2, FALSE)) {
1028 #ifdef HAVE_LIBGCRYPT
1029 crypto_bad = TRUE;
1030 expert_add_info(pinfo, tree, &ei_c1222_epsem_failed_authentication);
1031 #else /* HAVE_LIBGCRYPT */
1032 expert_add_info(pinfo, tree, &ei_c1222_epsem_not_authenticated);
1033 #endif /* HAVE_LIBGCRYPT */
1034 } else {
1035 crypto_good = TRUE;
1038 break;
1039 default:
1040 /* it's not encrypted */
1041 epsem_buffer = tvb_new_subset_remaining(tvb, offset);
1043 /* it's only encrypted if we have an undecrypted payload */
1044 if (encrypted) {
1045 proto_tree_add_item(tree, hf_c1222_epsem_total, tvb, offset, -1, ENC_NA);
1046 expert_add_info(pinfo, tree, &ei_c1222_epsem_not_decryped);
1047 local_offset = offset+len2-4;
1048 epsem_buffer = tvb;
1049 } else { /* it's not (now) encrypted */
1050 local_offset = 0;
1051 /* retrieve the ed_class if it's there */
1052 if (flags & C1222_EPSEM_FLAG_ED_CLASS_INCLUDED) {
1053 if (tvb_offset_exists(epsem_buffer, local_offset+4-1)) {
1054 proto_tree_add_item(tree, hf_c1222_epsem_ed_class, epsem_buffer, local_offset, 4, ENC_NA);
1055 local_offset += 4;
1056 } else {
1057 expert_add_info(pinfo, tree, &ei_c1222_ed_class_missing);
1060 /* what follows are one or more <epsem-data> elements possibly followed by
1061 * a <mac>. Each <epsem-data> element is defined as <service-length><res-req>,
1062 * so we fetch such pairs until there isn't anything left (except possibly
1063 * the <mac>).
1065 while (tvb_offset_exists(epsem_buffer, local_offset+(hasmac?5:1))) {
1066 if (ber_len_ok(epsem_buffer, local_offset)) {
1067 local_offset = dissect_ber_length(pinfo, tree, epsem_buffer, local_offset, (guint32 *)&len2, &ind);
1068 } else {
1069 expert_add_info(pinfo, tree, &ei_c1222_epsem_ber_length_error);
1070 return offset+len;
1072 if (tvb_offset_exists(epsem_buffer, local_offset+len2-1)) {
1073 cmd_err = tvb_get_guint8(epsem_buffer, local_offset);
1074 ct = proto_tree_add_item(tree, hf_c1222_epsem_total, epsem_buffer, local_offset, len2, ENC_NA);
1075 cmd_tree = proto_item_add_subtree(ct, ett_c1222_cmd);
1076 parse_c1222_detailed(epsem_buffer, pinfo, cmd_tree, cmd_err, (guint32 *)&len2, &local_offset);
1077 local_offset += len2;
1078 } else {
1079 expert_add_info(pinfo, tree, &ei_c1222_epsem_field_length_error);
1080 return offset+len;
1084 if (hasmac) {
1085 if (tvb_offset_exists(epsem_buffer, local_offset+4-1)) {
1086 yt = proto_tree_add_item(tree, hf_c1222_epsem_mac, epsem_buffer, local_offset, 4, ENC_NA);
1087 /* now we have enough information to fill in the crypto subtree */
1088 crypto_tree = proto_item_add_subtree(yt, ett_c1222_crypto);
1089 item = proto_tree_add_boolean(crypto_tree, hf_c1222_epsem_crypto_good, tvb, local_offset, 4, crypto_good);
1090 PROTO_ITEM_SET_GENERATED(item);
1091 item = proto_tree_add_boolean(crypto_tree, hf_c1222_epsem_crypto_bad, tvb, local_offset, 4, crypto_bad);
1092 PROTO_ITEM_SET_GENERATED(item);
1093 } else {
1094 expert_add_info(pinfo, tree, &ei_c1222_mac_missing);
1095 return offset+len;
1098 return offset;
1102 /*--- Included file: packet-c1222-fn.c ---*/
1103 #line 1 "../../asn1/c1222/packet-c1222-fn.c"
1106 static int
1107 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_) {
1108 #line 52 "../../asn1/c1222/c1222.cnf"
1109 FILL_START;
1110 offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1112 FILL_TABLE(aSO_context);
1116 return offset;
1121 static int
1122 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_) {
1123 offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1125 return offset;
1130 static int
1131 dissect_c1222_RELATIVE_OID(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
1132 offset = dissect_ber_relative_oid(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1134 return offset;
1138 static const value_string c1222_Called_AP_title_vals[] = {
1139 { 0, "called-ap-title-abs" },
1140 { 1, "called-ap-title-rel" },
1141 { 0, NULL }
1144 static const ber_choice_t Called_AP_title_choice[] = {
1145 { 0, &hf_c1222_called_ap_title_abs, BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_c1222_OBJECT_IDENTIFIER },
1146 { 1, &hf_c1222_called_ap_title_rel, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_RELATIVE_OID },
1147 { 0, NULL, 0, 0, 0, NULL }
1150 static int
1151 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_) {
1152 #line 57 "../../asn1/c1222/c1222.cnf"
1153 FILL_START;
1154 offset = dissect_ber_choice(actx, tree, tvb, offset,
1155 Called_AP_title_choice, hf_index, ett_c1222_Called_AP_title,
1156 NULL);
1158 FILL_TABLE_APTITLE(called_AP_title);
1162 return offset;
1167 static int
1168 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_) {
1169 offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1170 NULL);
1172 return offset;
1177 static int
1178 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_) {
1179 #line 62 "../../asn1/c1222/c1222.cnf"
1180 FILL_START;
1181 offset = dissect_c1222_AP_invocation_id(implicit_tag, tvb, offset, actx, tree, hf_index);
1183 FILL_TABLE(called_AP_invocation_id);
1187 return offset;
1191 static const value_string c1222_Calling_AP_title_vals[] = {
1192 { 0, "calling-ap-title-abs" },
1193 { 1, "calling-ap-title-rel" },
1194 { 0, NULL }
1197 static const ber_choice_t Calling_AP_title_choice[] = {
1198 { 0, &hf_c1222_calling_ap_title_abs, BER_CLASS_UNI, BER_UNI_TAG_OID, BER_FLAGS_NOOWNTAG, dissect_c1222_OBJECT_IDENTIFIER },
1199 { 1, &hf_c1222_calling_ap_title_rel, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_RELATIVE_OID },
1200 { 0, NULL, 0, 0, 0, NULL }
1203 static int
1204 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_) {
1205 #line 87 "../../asn1/c1222/c1222.cnf"
1206 FILL_START;
1207 offset = dissect_ber_choice(actx, tree, tvb, offset,
1208 Calling_AP_title_choice, hf_index, ett_c1222_Calling_AP_title,
1209 NULL);
1211 FILL_TABLE_APTITLE(calling_AP_title);
1215 return offset;
1220 static int
1221 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_) {
1222 offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1223 NULL);
1225 return offset;
1230 static int
1231 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_) {
1232 #line 67 "../../asn1/c1222/c1222.cnf"
1233 FILL_START;
1234 offset = dissect_c1222_AE_qualifier(implicit_tag, tvb, offset, actx, tree, hf_index);
1236 FILL_TABLE(calling_AE_qualifier);
1240 return offset;
1245 static int
1246 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_) {
1247 #line 72 "../../asn1/c1222/c1222.cnf"
1248 FILL_START;
1249 offset = dissect_c1222_AP_invocation_id(implicit_tag, tvb, offset, actx, tree, hf_index);
1251 FILL_TABLE(calling_AP_invocation_id);
1255 return offset;
1260 static int
1261 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_) {
1262 #line 77 "../../asn1/c1222/c1222.cnf"
1263 FILL_START;
1264 offset = dissect_ber_object_identifier(implicit_tag, actx, tree, tvb, offset, hf_index, NULL);
1266 FILL_TABLE(mechanism_name);
1270 return offset;
1275 static int
1276 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_) {
1277 offset = dissect_ber_integer(implicit_tag, actx, tree, tvb, offset, hf_index,
1278 NULL);
1280 return offset;
1285 static int
1286 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_) {
1287 #line 92 "../../asn1/c1222/c1222.cnf"
1288 FILL_START;
1289 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1290 NULL);
1292 FILL_TABLE(key_id_element);
1296 return offset;
1301 static int
1302 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_) {
1303 #line 97 "../../asn1/c1222/c1222.cnf"
1304 FILL_START;
1305 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1306 NULL);
1308 FILL_TABLE(iv_element);
1312 return offset;
1316 static const ber_sequence_t Calling_authentication_value_c1222_U_sequence[] = {
1317 { &hf_c1222_key_id_element, BER_CLASS_CON, 0, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_c1222_Key_id_element },
1318 { &hf_c1222_iv_element , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_c1222_Iv_element },
1319 { NULL, 0, 0, 0, NULL }
1322 static int
1323 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_) {
1324 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1325 Calling_authentication_value_c1222_U_sequence, hf_index, ett_c1222_Calling_authentication_value_c1222_U);
1327 return offset;
1332 static int
1333 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_) {
1334 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1335 hf_index, BER_CLASS_CON, 1, TRUE, dissect_c1222_Calling_authentication_value_c1222_U);
1337 return offset;
1342 static int
1343 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_) {
1344 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1345 NULL);
1347 return offset;
1352 static int
1353 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_) {
1354 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1355 NULL);
1357 return offset;
1362 static int
1363 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_) {
1364 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1365 NULL);
1367 return offset;
1371 static const value_string c1222_Calling_authentication_value_c1221_U_vals[] = {
1372 { 0, "c1221-auth-identification" },
1373 { 0, "c1221-auth-request" },
1374 { 0, "c1221-auth-response" },
1375 { 0, NULL }
1378 static const ber_choice_t Calling_authentication_value_c1221_U_choice[] = {
1379 { 0, &hf_c1222_c1221_auth_identification, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING_SIZE_CONSTR001 },
1380 { 0, &hf_c1222_c1221_auth_request, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING_SIZE_1_255 },
1381 { 0, &hf_c1222_c1221_auth_response, BER_CLASS_CON, 0, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING_SIZE_CONSTR002 },
1382 { 0, NULL, 0, 0, 0, NULL }
1385 static int
1386 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_) {
1387 offset = dissect_ber_choice(actx, tree, tvb, offset,
1388 Calling_authentication_value_c1221_U_choice, hf_index, ett_c1222_Calling_authentication_value_c1221_U,
1389 NULL);
1391 return offset;
1396 static int
1397 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_) {
1398 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1399 hf_index, BER_CLASS_CON, 0, TRUE, dissect_c1222_Calling_authentication_value_c1221_U);
1401 return offset;
1405 static const value_string c1222_Calling_authentication_value_single_asn1_vals[] = {
1406 { 1, "calling-authentication-value-c1222" },
1407 { 0, "calling-authentication-value-c1221" },
1408 { 0, NULL }
1411 static const ber_choice_t Calling_authentication_value_single_asn1_choice[] = {
1412 { 1, &hf_c1222_calling_authentication_value_c1222, BER_CLASS_CON, 1, BER_FLAGS_NOOWNTAG, dissect_c1222_Calling_authentication_value_c1222 },
1413 { 0, &hf_c1222_calling_authentication_value_c1221, BER_CLASS_CON, 0, BER_FLAGS_NOOWNTAG, dissect_c1222_Calling_authentication_value_c1221 },
1414 { 0, NULL, 0, 0, 0, NULL }
1417 static int
1418 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_) {
1419 offset = dissect_ber_choice(actx, tree, tvb, offset,
1420 Calling_authentication_value_single_asn1_choice, hf_index, ett_c1222_Calling_authentication_value_single_asn1,
1421 NULL);
1423 return offset;
1428 static int
1429 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_) {
1430 offset = dissect_ber_octet_string(implicit_tag, actx, tree, tvb, offset, hf_index,
1431 NULL);
1433 return offset;
1437 static const value_string c1222_Authentication_value_encoding_vals[] = {
1438 { 0, "calling-authentication-value-single-asn1" },
1439 { 1, "calling-authentication-value-octet-aligned" },
1440 { 0, NULL }
1443 static const ber_choice_t Authentication_value_encoding_choice[] = {
1444 { 0, &hf_c1222_calling_authentication_value_single_asn1, BER_CLASS_CON, 0, 0, dissect_c1222_Calling_authentication_value_single_asn1 },
1445 { 1, &hf_c1222_calling_authentication_value_octet_aligned, BER_CLASS_CON, 1, BER_FLAGS_IMPLTAG, dissect_c1222_OCTET_STRING },
1446 { 0, NULL, 0, 0, 0, NULL }
1449 static int
1450 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_) {
1451 offset = dissect_ber_choice(actx, tree, tvb, offset,
1452 Authentication_value_encoding_choice, hf_index, ett_c1222_Authentication_value_encoding,
1453 NULL);
1455 return offset;
1459 static const ber_sequence_t Calling_authentication_value_U_sequence[] = {
1460 { &hf_c1222_calling_authentication_value_indirect, BER_CLASS_UNI, BER_UNI_TAG_INTEGER, BER_FLAGS_OPTIONAL|BER_FLAGS_NOOWNTAG, dissect_c1222_INTEGER },
1461 { &hf_c1222_calling_authentication_value_encoding, BER_CLASS_ANY/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG|BER_FLAGS_NOTCHKTAG, dissect_c1222_Authentication_value_encoding },
1462 { NULL, 0, 0, 0, NULL }
1465 static int
1466 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_) {
1467 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1468 Calling_authentication_value_U_sequence, hf_index, ett_c1222_Calling_authentication_value_U);
1470 return offset;
1475 static int
1476 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_) {
1477 #line 82 "../../asn1/c1222/c1222.cnf"
1478 FILL_START;
1479 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1480 hf_index, BER_CLASS_CON, 2, TRUE, dissect_c1222_Calling_authentication_value_U);
1482 FILL_TABLE(calling_authentication_value);
1486 return offset;
1491 static int
1492 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_) {
1493 #line 28 "../../asn1/c1222/c1222.cnf"
1494 gint8 end_device_class;
1495 gboolean pc, ind;
1496 gint32 tag;
1497 guint32 len;
1498 proto_item *tf = NULL;
1499 proto_tree *epsem_tree = NULL;
1500 FILL_START;
1502 /* get Tag and Length */
1503 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &end_device_class, &pc, &tag);
1504 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1505 FILL_TABLE_TRUNCATE(user_information, len+offset-start_offset);
1506 if (tag == 0x8) { /* BER_TAG_EXTERNAL */
1507 offset = dissect_ber_identifier(actx->pinfo, tree, tvb, offset, &end_device_class, &pc, &tag);
1508 offset = dissect_ber_length(actx->pinfo, tree, tvb, offset, &len, &ind);
1509 if (tag == 0x1) { /* implicit octet string */
1510 tf = proto_tree_add_item(tree, hf_c1222_user_information, tvb, offset, len, ENC_NA);
1511 epsem_tree = proto_item_add_subtree(tf, ett_c1222_epsem);
1512 dissect_epsem(tvb, offset, len, actx->pinfo, epsem_tree);
1513 offset += len;
1519 return offset;
1523 static const ber_sequence_t MESSAGE_U_sequence[] = {
1524 { &hf_c1222_aSO_context , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_c1222_ASO_qualifier },
1525 { &hf_c1222_called_AP_title, BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_c1222_Called_AP_title },
1526 { &hf_c1222_called_AP_invocation_id, BER_CLASS_CON, 4, BER_FLAGS_OPTIONAL, dissect_c1222_Called_AP_invocation_id },
1527 { &hf_c1222_calling_AP_title, BER_CLASS_CON, 6, BER_FLAGS_OPTIONAL|BER_FLAGS_NOTCHKTAG, dissect_c1222_Calling_AP_title },
1528 { &hf_c1222_calling_AE_qualifier, BER_CLASS_CON, 7, BER_FLAGS_OPTIONAL, dissect_c1222_Calling_AE_qualifier },
1529 { &hf_c1222_calling_AP_invocation_id, BER_CLASS_CON, 8, 0, dissect_c1222_Calling_AP_invocation_id },
1530 { &hf_c1222_mechanism_name, BER_CLASS_CON, 11, BER_FLAGS_OPTIONAL|BER_FLAGS_IMPLTAG, dissect_c1222_Mechanism_name },
1531 { &hf_c1222_calling_authentication_value, BER_CLASS_CON, 12, BER_FLAGS_OPTIONAL, dissect_c1222_Calling_authentication_value },
1532 { &hf_c1222_user_information, BER_CLASS_CON, 30, 0, dissect_c1222_User_information },
1533 { NULL, 0, 0, 0, NULL }
1536 static int
1537 dissect_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_) {
1538 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
1539 MESSAGE_U_sequence, hf_index, ett_c1222_MESSAGE_U);
1541 return offset;
1546 static int
1547 dissect_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_) {
1548 #line 102 "../../asn1/c1222/c1222.cnf"
1549 /**/#ifdef HAVE_LIBGCRYPT
1550 clear_canon();
1551 /**/#endif
1552 offset = dissect_ber_tagged_type(implicit_tag, actx, tree, tvb, offset,
1553 hf_index, BER_CLASS_APP, 0, TRUE, dissect_c1222_MESSAGE_U);
1557 return offset;
1560 /*--- PDUs ---*/
1562 static void dissect_MESSAGE_PDU(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {
1563 asn1_ctx_t asn1_ctx;
1564 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1565 dissect_c1222_MESSAGE(FALSE, tvb, 0, &asn1_ctx, tree, hf_c1222_MESSAGE_PDU);
1569 /*--- End of included file: packet-c1222-fn.c ---*/
1570 #line 1051 "../../asn1/c1222/packet-c1222-template.c"
1573 * Dissects a a full (reassembled) C12.22 message.
1575 * \param tvb the tv buffer of the current data
1576 * \param pinfo the packet info of the current data
1577 * \param tree the tree to append this item to
1579 static int
1580 dissect_c1222_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1582 proto_item *c1222_item = NULL;
1583 proto_tree *c1222_tree = NULL;
1585 /* make entry in the Protocol column on summary display */
1586 col_set_str(pinfo->cinfo, COL_PROTOCOL, PNAME);
1588 /* create the c1222 protocol tree */
1589 if (tree) {
1590 c1222_item = proto_tree_add_item(tree, proto_c1222, tvb, 0, -1, ENC_NA);
1591 c1222_tree = proto_item_add_subtree(c1222_item, ett_c1222);
1592 dissect_MESSAGE_PDU(tvb, pinfo, c1222_tree);
1595 return tvb_length(tvb);
1599 * Fetches the length of an entire C12.22 message to assist in reassembly.
1601 * \param pinfo the packet info of the current data
1602 * \param tvb the tv buffer of the current data
1603 * \param offset the offset in the tvb
1604 * \returns length of entire C12.22 message
1606 static guint
1607 get_c1222_message_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
1609 int orig_offset;
1610 guint length;
1611 gboolean ind;
1613 orig_offset = offset;
1614 /* note that this assumes a Tag length of 1 which is always valid for C12.22 */
1615 offset = dissect_ber_length(pinfo, NULL, tvb, offset+1, &length, &ind);
1616 return length+(offset - orig_offset);
1620 * Reassembles and dissects C12.22 messages.
1622 * \param tvb the tv buffer of the current data
1623 * \param pinfo the packet info of the current data
1624 * \param tree the tree to append this item to
1626 static int
1627 dissect_c1222(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1629 tcp_dissect_pdus(tvb, pinfo, tree, c1222_desegment, 5,
1630 get_c1222_message_len, dissect_c1222_common, data);
1631 return tvb_length(tvb);
1634 /*--- proto_register_c1222 -------------------------------------------*/
1635 void proto_register_c1222(void) {
1637 /* List of fields */
1638 static hf_register_info hf[] = {
1639 { &hf_c1222_epsem_flags,
1640 { "C12.22 EPSEM Flags", "c1222.epsem.flags",
1641 FT_UINT8, BASE_HEX,
1642 NULL, 0x0,
1643 NULL, HFILL }
1645 { &hf_c1222_epsem_flags_reserved,
1646 { "C12.22 Reserved Flag", "c1222.epsem.flags.reserved",
1647 FT_BOOLEAN, 8,
1648 NULL, C1222_EPSEM_FLAG_RESERVED,
1649 NULL, HFILL }
1651 { &hf_c1222_epsem_flags_recovery,
1652 { "C12.22 Recovery Flag", "c1222.epsem.flags.recovery",
1653 FT_BOOLEAN, 8,
1654 NULL, C1222_EPSEM_FLAG_RECOVERY_SESSION,
1655 NULL, HFILL }
1657 { &hf_c1222_epsem_flags_proxy,
1658 { "C12.22 Proxy Service Used Flag", "c1222.epsem.flags.proxy",
1659 FT_BOOLEAN, 8,
1660 NULL, C1222_EPSEM_FLAG_PROXY_SERVICE_USED,
1661 NULL, HFILL }
1663 { &hf_c1222_epsem_flags_ed_class,
1664 { "C12.22 ED Class Flag", "c1222.epsem.flags.ed_class",
1665 FT_BOOLEAN, 8,
1666 NULL, C1222_EPSEM_FLAG_ED_CLASS_INCLUDED,
1667 NULL, HFILL }
1669 { &hf_c1222_epsem_flags_security_modes,
1670 { "C12.22 Security Mode Flags", "c1222.epsem.flags.security",
1671 FT_UINT8, BASE_HEX,
1672 VALS(c1222_security_modes), C1222_EPSEM_FLAG_SECURITY_MODE,
1673 NULL, HFILL }
1675 { &hf_c1222_epsem_flags_response_control,
1676 { "C12.22 Response Control Flags", "c1222.epsem.flags.response_control",
1677 FT_UINT8, BASE_HEX,
1678 VALS(c1222_response_control), C1222_EPSEM_FLAG_RESPONSE_CONTROL,
1679 NULL, HFILL }
1681 { &hf_c1222_epsem_ed_class,
1682 { "C12.22 EPSEM ED Class", "c1222.epsem.edclass",
1683 FT_BYTES, BASE_NONE,
1684 NULL, 0x0,
1685 NULL, HFILL }
1687 { &hf_c1222_epsem_total,
1688 { "C12.22 EPSEM", "c1222.epsem.data",
1689 FT_BYTES, BASE_NONE,
1690 NULL, 0x0,
1691 NULL, HFILL }
1693 { &hf_c1222_epsem_mac,
1694 { "C12.22 EPSEM MAC", "c1222.epsem.mac",
1695 FT_BYTES, BASE_NONE,
1696 NULL, 0x0,
1697 NULL, HFILL }
1699 { &hf_c1222_cmd,
1700 { "C12.22 Command", "c1222.cmd",
1701 FT_UINT8, BASE_HEX,
1702 VALS(commandnames), 0x0,
1703 NULL, HFILL }
1705 { &hf_c1222_err,
1706 { "C12.22 Response", "c1222.err",
1707 FT_UINT8, BASE_HEX,
1708 VALS(commandnames), 0x0,
1709 NULL, HFILL }
1711 { &hf_c1222_logon_id,
1712 { "C12.22 Logon User-Id", "c1222.logon.id",
1713 FT_UINT16, BASE_DEC,
1714 NULL, 0x0,
1715 NULL, HFILL }
1717 { &hf_c1222_logon_user,
1718 { "C12.22 Logon User", "c1222.logon.user",
1719 FT_STRING, BASE_NONE,
1720 NULL, 0x0,
1721 NULL, HFILL }
1723 { &hf_c1222_security_password,
1724 { "C12.22 Security Password", "c1222.security.password",
1725 FT_STRING, BASE_NONE,
1726 NULL, 0x0,
1727 NULL, HFILL }
1729 { &hf_c1222_auth_len,
1730 { "C12.22 Authenticate Request Length", "c1222.authenticate.len",
1731 FT_UINT8, BASE_DEC,
1732 NULL, 0x0,
1733 NULL, HFILL }
1735 { &hf_c1222_auth_data,
1736 { "C12.22 Authenticate Data", "c1222.authenticate.data",
1737 FT_BYTES, BASE_NONE,
1738 NULL, 0x0,
1739 NULL, HFILL }
1741 { &hf_c1222_read_table,
1742 { "C12.22 Table", "c1222.read.table",
1743 FT_UINT16, BASE_HEX,
1744 NULL, 0x0,
1745 NULL, HFILL }
1747 { &hf_c1222_read_offset,
1748 { "C12.22 Offset", "c1222.read.offset",
1749 FT_UINT24, BASE_HEX,
1750 NULL, 0x0,
1751 NULL, HFILL }
1753 { &hf_c1222_read_count,
1754 { "C12.22 Count", "c1222.read.count",
1755 FT_UINT16, BASE_DEC,
1756 NULL, 0x0,
1757 NULL, HFILL }
1759 { &hf_c1222_write_table,
1760 { "C12.22 Table", "c1222.write.table",
1761 FT_UINT16, BASE_HEX,
1762 NULL, 0x0,
1763 NULL, HFILL }
1765 { &hf_c1222_write_offset,
1766 { "C12.22 Offset", "c1222.write.offset",
1767 FT_UINT24, BASE_HEX,
1768 NULL, 0x0,
1769 NULL, HFILL }
1771 { &hf_c1222_write_size,
1772 { "C12.22 Table Size", "c1222.write.size",
1773 FT_UINT16, BASE_HEX,
1774 NULL, 0x0,
1775 NULL, HFILL }
1777 { &hf_c1222_write_data,
1778 { "C12.22 Table Data", "c1222.write.data",
1779 FT_BYTES, BASE_NONE,
1780 NULL, 0x0,
1781 NULL, HFILL }
1783 { &hf_c1222_write_chksum,
1784 { "C12.22 Table Data Checksum", "c1222.write.chksum",
1785 FT_UINT8, BASE_HEX,
1786 NULL, 0x0,
1787 NULL, HFILL }
1789 { &hf_c1222_procedure_num,
1790 { "C12.22 Procedure Number", "c1222.procedure.num",
1791 FT_UINT16, BASE_DEC,
1792 NULL, 0x7ff,
1793 NULL, HFILL }
1795 { &hf_c1222_neg_pkt_size,
1796 { "C12.22 Negotiate Packet Size", "c1222.negotiate.pktsize",
1797 FT_UINT16, BASE_DEC,
1798 NULL, 0x0,
1799 NULL, HFILL }
1801 { &hf_c1222_neg_nbr_pkts,
1802 { "C12.22 Negotiate Number of Packets", "c1222.negotiate.numpkts",
1803 FT_UINT8, BASE_DEC,
1804 NULL, 0x0,
1805 NULL, HFILL }
1807 { &hf_c1222_wait_secs,
1808 { "C12.22 Wait Seconds", "c1222.wait.seconds",
1809 FT_UINT8, BASE_DEC,
1810 NULL, 0x0,
1811 NULL, HFILL }
1813 { &hf_c1222_timing_setup_traffic,
1814 { "C12.22 Timing Setup Channel Traffic Timeout", "c1222.timingsetup.traffic",
1815 FT_UINT8, BASE_DEC,
1816 NULL, 0x0,
1817 NULL, HFILL }
1819 { &hf_c1222_timing_setup_inter_char,
1820 { "C12.22 Timing Setup Intercharacter Timeout", "c1222.timingsetup.interchar",
1821 FT_UINT8, BASE_DEC,
1822 NULL, 0x0,
1823 NULL, HFILL }
1825 { &hf_c1222_timing_setup_resp_to,
1826 { "C12.22 Timing Setup Response Timeout", "c1222.timingsetup.respto",
1827 FT_UINT8, BASE_DEC,
1828 NULL, 0x0,
1829 NULL, HFILL }
1831 { &hf_c1222_timing_setup_nbr_retries,
1832 { "C12.22 Timing Setup Number of Retries", "c1222.timingsetup.nbrretries",
1833 FT_UINT8, BASE_DEC,
1834 NULL, 0x0,
1835 NULL, HFILL }
1837 { &hf_c1222_data,
1838 { "C12.22 data", "c1222.data",
1839 FT_BYTES, BASE_NONE,
1840 NULL, 0x0,
1841 NULL, HFILL }
1843 { &hf_c1222_epsem_crypto_good,
1844 { "Crypto good", "c1222.crypto_good",
1845 FT_BOOLEAN, BASE_NONE,
1846 NULL, 0x0,
1847 "True: crypto ok; False: doesn't match or not checked", HFILL }
1849 { &hf_c1222_epsem_crypto_bad,
1850 { "Crypto bad", "c1222.crypto_bad",
1851 FT_BOOLEAN, BASE_NONE,
1852 NULL, 0x0,
1853 "True: crypto bad; False: crypto ok or not checked", HFILL }
1856 /*--- Included file: packet-c1222-hfarr.c ---*/
1857 #line 1 "../../asn1/c1222/packet-c1222-hfarr.c"
1858 { &hf_c1222_MESSAGE_PDU,
1859 { "MESSAGE", "c1222.MESSAGE_element",
1860 FT_NONE, BASE_NONE, NULL, 0,
1861 NULL, HFILL }},
1862 { &hf_c1222_aSO_context,
1863 { "aSO-context", "c1222.aSO_context",
1864 FT_OID, BASE_NONE, NULL, 0,
1865 "ASO_qualifier", HFILL }},
1866 { &hf_c1222_called_AP_title,
1867 { "called-AP-title", "c1222.called_AP_title",
1868 FT_UINT32, BASE_DEC, VALS(c1222_Called_AP_title_vals), 0,
1869 NULL, HFILL }},
1870 { &hf_c1222_called_AP_invocation_id,
1871 { "called-AP-invocation-id", "c1222.called_AP_invocation_id",
1872 FT_UINT32, BASE_DEC, NULL, 0,
1873 NULL, HFILL }},
1874 { &hf_c1222_calling_AP_title,
1875 { "calling-AP-title", "c1222.calling_AP_title",
1876 FT_UINT32, BASE_DEC, VALS(c1222_Calling_AP_title_vals), 0,
1877 NULL, HFILL }},
1878 { &hf_c1222_calling_AE_qualifier,
1879 { "calling-AE-qualifier", "c1222.calling_AE_qualifier",
1880 FT_UINT32, BASE_DEC, NULL, 0,
1881 NULL, HFILL }},
1882 { &hf_c1222_calling_AP_invocation_id,
1883 { "calling-AP-invocation-id", "c1222.calling_AP_invocation_id",
1884 FT_UINT32, BASE_DEC, NULL, 0,
1885 NULL, HFILL }},
1886 { &hf_c1222_mechanism_name,
1887 { "mechanism-name", "c1222.mechanism_name",
1888 FT_OID, BASE_NONE, NULL, 0,
1889 NULL, HFILL }},
1890 { &hf_c1222_calling_authentication_value,
1891 { "calling-authentication-value", "c1222.calling_authentication_value_element",
1892 FT_NONE, BASE_NONE, NULL, 0,
1893 NULL, HFILL }},
1894 { &hf_c1222_user_information,
1895 { "user-information", "c1222.user_information_element",
1896 FT_NONE, BASE_NONE, NULL, 0,
1897 NULL, HFILL }},
1898 { &hf_c1222_called_ap_title_abs,
1899 { "called-ap-title-abs", "c1222.called_ap_title_abs",
1900 FT_OID, BASE_NONE, NULL, 0,
1901 "OBJECT_IDENTIFIER", HFILL }},
1902 { &hf_c1222_called_ap_title_rel,
1903 { "called-ap-title-rel", "c1222.called_ap_title_rel",
1904 FT_REL_OID, BASE_NONE, NULL, 0,
1905 "RELATIVE_OID", HFILL }},
1906 { &hf_c1222_calling_ap_title_abs,
1907 { "calling-ap-title-abs", "c1222.calling_ap_title_abs",
1908 FT_OID, BASE_NONE, NULL, 0,
1909 "OBJECT_IDENTIFIER", HFILL }},
1910 { &hf_c1222_calling_ap_title_rel,
1911 { "calling-ap-title-rel", "c1222.calling_ap_title_rel",
1912 FT_REL_OID, BASE_NONE, NULL, 0,
1913 "RELATIVE_OID", HFILL }},
1914 { &hf_c1222_calling_authentication_value_indirect,
1915 { "calling-authentication-value-indirect", "c1222.calling_authentication_value_indirect",
1916 FT_INT32, BASE_DEC, NULL, 0,
1917 "INTEGER", HFILL }},
1918 { &hf_c1222_calling_authentication_value_encoding,
1919 { "calling-authentication-value-encoding", "c1222.calling_authentication_value_encoding",
1920 FT_UINT32, BASE_DEC, VALS(c1222_Authentication_value_encoding_vals), 0,
1921 "Authentication_value_encoding", HFILL }},
1922 { &hf_c1222_calling_authentication_value_single_asn1,
1923 { "calling-authentication-value-single-asn1", "c1222.calling_authentication_value_single_asn1",
1924 FT_UINT32, BASE_DEC, VALS(c1222_Calling_authentication_value_single_asn1_vals), 0,
1925 NULL, HFILL }},
1926 { &hf_c1222_calling_authentication_value_octet_aligned,
1927 { "calling-authentication-value-octet-aligned", "c1222.calling_authentication_value_octet_aligned",
1928 FT_BYTES, BASE_NONE, NULL, 0,
1929 "OCTET_STRING", HFILL }},
1930 { &hf_c1222_calling_authentication_value_c1222,
1931 { "calling-authentication-value-c1222", "c1222.calling_authentication_value_c1222_element",
1932 FT_NONE, BASE_NONE, NULL, 0,
1933 NULL, HFILL }},
1934 { &hf_c1222_calling_authentication_value_c1221,
1935 { "calling-authentication-value-c1221", "c1222.calling_authentication_value_c1221",
1936 FT_UINT32, BASE_DEC, VALS(c1222_Calling_authentication_value_c1221_U_vals), 0,
1937 NULL, HFILL }},
1938 { &hf_c1222_key_id_element,
1939 { "key-id-element", "c1222.key_id_element",
1940 FT_BYTES, BASE_NONE, NULL, 0,
1941 NULL, HFILL }},
1942 { &hf_c1222_iv_element,
1943 { "iv-element", "c1222.iv_element",
1944 FT_BYTES, BASE_NONE, NULL, 0,
1945 NULL, HFILL }},
1946 { &hf_c1222_c1221_auth_identification,
1947 { "c1221-auth-identification", "c1222.c1221_auth_identification",
1948 FT_BYTES, BASE_NONE, NULL, 0,
1949 "OCTET_STRING_SIZE_CONSTR001", HFILL }},
1950 { &hf_c1222_c1221_auth_request,
1951 { "c1221-auth-request", "c1222.c1221_auth_request",
1952 FT_BYTES, BASE_NONE, NULL, 0,
1953 "OCTET_STRING_SIZE_1_255", HFILL }},
1954 { &hf_c1222_c1221_auth_response,
1955 { "c1221-auth-response", "c1222.c1221_auth_response",
1956 FT_BYTES, BASE_NONE, NULL, 0,
1957 "OCTET_STRING_SIZE_CONSTR002", HFILL }},
1959 /*--- End of included file: packet-c1222-hfarr.c ---*/
1960 #line 1336 "../../asn1/c1222/packet-c1222-template.c"
1963 /* List of subtrees */
1964 static gint *ett[] = {
1965 &ett_c1222,
1966 &ett_c1222_epsem,
1967 &ett_c1222_flags,
1968 &ett_c1222_crypto,
1969 &ett_c1222_cmd,
1971 /*--- Included file: packet-c1222-ettarr.c ---*/
1972 #line 1 "../../asn1/c1222/packet-c1222-ettarr.c"
1973 &ett_c1222_MESSAGE_U,
1974 &ett_c1222_Called_AP_title,
1975 &ett_c1222_Calling_AP_title,
1976 &ett_c1222_Calling_authentication_value_U,
1977 &ett_c1222_Authentication_value_encoding,
1978 &ett_c1222_Calling_authentication_value_single_asn1,
1979 &ett_c1222_Calling_authentication_value_c1222_U,
1980 &ett_c1222_Calling_authentication_value_c1221_U,
1982 /*--- End of included file: packet-c1222-ettarr.c ---*/
1983 #line 1346 "../../asn1/c1222/packet-c1222-template.c"
1986 static ei_register_info ei[] = {
1987 { &ei_c1222_command_truncated, { "c1222.command_truncated", PI_MALFORMED, PI_ERROR, "C12.22 command truncated", EXPFILL }},
1988 { &ei_c1222_bad_checksum, { "c1222.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
1989 { &ei_c1222_epsem_missing, { "c1222.epsem.missing", PI_MALFORMED, PI_ERROR, "C12.22 EPSEM missing", EXPFILL }},
1990 #ifdef HAVE_LIBGCRYPT
1991 { &ei_c1222_epsem_failed_authentication, { "c1222.epsem.failed_authentication", PI_SECURITY, PI_ERROR, "C12.22 EPSEM failed authentication", EXPFILL }},
1992 #else
1993 { &ei_c1222_epsem_not_authenticated, { "c1222.epsem.not_authenticated", PI_SECURITY, PI_WARN, "C12.22 EPSEM could not be authenticated", EXPFILL }},
1994 #endif
1995 { &ei_c1222_epsem_not_decryped, { "c1222.epsem.not_decryped", PI_UNDECODED, PI_WARN, "C12.22 EPSEM could not be decrypted", EXPFILL }},
1996 { &ei_c1222_ed_class_missing, { "c1222.ed_class_missing", PI_SECURITY, PI_ERROR, "C12.22 ED Class missing", EXPFILL }},
1997 { &ei_c1222_epsem_ber_length_error, { "c1222.epsem.ber_length_error", PI_MALFORMED, PI_ERROR, "C12.22 EPSEM BER length error", EXPFILL }},
1998 { &ei_c1222_epsem_field_length_error, { "c1222.epsem.field_length_error", PI_MALFORMED, PI_ERROR, "C12.22 EPSEM field length error", EXPFILL }},
1999 { &ei_c1222_mac_missing, { "c1222.mac_missing", PI_MALFORMED, PI_ERROR, "C12.22 MAC missing", EXPFILL }},
2002 expert_module_t* expert_c1222;
2003 module_t *c1222_module;
2005 #ifdef HAVE_LIBGCRYPT
2006 static uat_field_t c1222_uat_flds[] = {
2007 UAT_FLD_HEX(c1222_users,keynum,"Key ID","Key identifier in hexadecimal"),
2008 UAT_FLD_BUFFER(c1222_users, key, "Key", "Encryption key as 16-byte hex string"),
2009 UAT_END_FIELDS
2011 #endif /* HAVE_LIBGCRYPT */
2013 /* Register protocol */
2014 proto_c1222 = proto_register_protocol(PNAME, PSNAME, PFNAME);
2015 /* Register fields and subtrees */
2016 proto_register_field_array(proto_c1222, hf, array_length(hf));
2017 proto_register_subtree_array(ett, array_length(ett));
2018 expert_c1222 = expert_register_protocol(proto_c1222);
2019 expert_register_field_array(expert_c1222, ei, array_length(ei));
2020 c1222_module = prefs_register_protocol(proto_c1222, proto_reg_handoff_c1222);
2021 prefs_register_bool_preference(c1222_module, "desegment",
2022 "Reassemble all C12.22 messages spanning multiple TCP segments",
2023 "Whether the C12.22 dissector should reassemble all messages spanning multiple TCP segments",
2024 &c1222_desegment);
2025 prefs_register_string_preference(c1222_module, "baseoid", "Base OID to use for relative OIDs",
2026 "Base object identifier for use in resolving relative object identifiers",
2027 &c1222_baseoid_str);
2028 #ifdef HAVE_LIBGCRYPT
2029 prefs_register_bool_preference(c1222_module, "decrypt",
2030 "Verify crypto for all applicable C12.22 messages",
2031 "Whether the C12.22 dissector should verify the crypto for all relevant messages",
2032 &c1222_decrypt);
2034 c1222_uat = uat_new("Decryption Table",
2035 sizeof(c1222_uat_data_t), /* record size */
2036 "c1222_decryption_table", /* filename */
2037 TRUE, /* from_profile */
2038 (void**)&c1222_uat_data, /* data_ptr */
2039 &num_c1222_uat_data, /* numitems_ptr */
2040 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
2041 NULL, /* help */
2042 NULL, /* copy callback */
2043 c1222_uat_data_update_cb, /* update callback */
2044 NULL, /* free callback */
2045 NULL, /* post update callback */
2046 c1222_uat_flds); /* UAT field definitions */
2048 prefs_register_uat_preference(c1222_module,
2049 "decryption_table",
2050 "Decryption Table",
2051 "Table of security parameters for decryption of C12.22 packets",
2052 c1222_uat);
2053 #endif /* HAVE_LIBGCRYPT */
2056 /*--- proto_reg_handoff_c1222 ---------------------------------------*/
2057 void
2058 proto_reg_handoff_c1222(void)
2060 static gboolean initialized = FALSE;
2061 guint8 *temp = NULL;
2063 if( !initialized ) {
2064 c1222_handle = new_create_dissector_handle(dissect_c1222, proto_c1222);
2065 c1222_udp_handle = new_create_dissector_handle(dissect_c1222_common, proto_c1222);
2066 dissector_add_uint("tcp.port", global_c1222_port, c1222_handle);
2067 dissector_add_uint("udp.port", global_c1222_port, c1222_udp_handle);
2068 initialized = TRUE;
2070 c1222_baseoid_len = oid_string2encoded(c1222_baseoid_str, &temp);
2071 c1222_baseoid = (guint8 *)wmem_realloc(wmem_epan_scope(), c1222_baseoid, c1222_baseoid_len);
2072 memcpy(c1222_baseoid, temp, c1222_baseoid_len);
2075 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2077 * Local variables:
2078 * c-basic-offset: 2
2079 * tab-width: 8
2080 * indent-tabs-mode: nil
2081 * End:
2083 * vi: set shiftwidth=2 tabstop=8 expandtab:
2084 * :indentSize=2:tabSize=8:noTabs=true: