1 /* Do not modify this file. Changes will be overwritten. */
2 /* Generated automatically by the ASN.1 to Wireshark dissector compiler */
4 /* asn2wrs.py -b -q -L -p c1222 -c ./c1222.cnf -s ./packet-c1222-template -D . -O ../.. c1222.asn */
7 * Routines for ANSI C12.22 packet dissection
8 * Copyright 2010, Edward J. Beroset, edward.beroset@elster.com
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include <epan/packet.h>
20 #include <epan/conversation.h>
21 #include <epan/expert.h>
22 #include <epan/prefs.h>
23 #include <epan/strutil.h>
25 #include <epan/oids.h>
26 #include <wsutil/eax.h>
27 #include <wsutil/array.h>
28 #include "packet-ber.h"
29 #include "packet-tcp.h"
30 #include "packet-c1222.h"
32 #define PNAME "ANSI C12.22"
33 #define PSNAME "C12.22"
34 #define PFNAME "c1222"
35 #define C1222_PORT 1153 /* TCP port */
37 /* C12.22 flag definitions */
38 #define C1222_EPSEM_FLAG_RESERVED 0x80
39 #define C1222_EPSEM_FLAG_RECOVERY_SESSION 0x40
40 #define C1222_EPSEM_FLAG_PROXY_SERVICE_USED 0x20
41 #define C1222_EPSEM_FLAG_ED_CLASS_INCLUDED 0x10
42 #define C1222_EPSEM_FLAG_SECURITY_MODE 0x0c
43 #define C1222_EPSEM_FLAG_RESPONSE_CONTROL 0x03
45 #define C1222_PROCEDURE_RESPONSE 0xf000
46 #define C1222_PROCEDURE_MFG 0x0800
47 #define C1222_PROCEDURE_NUMBER 0x07ff
49 /* if the packet is encrypted, it can be
50 * good, bad, or simply not checked
52 #define C1222_EPSEM_CRYPTO_GOOD 0x01
53 #define C1222_EPSEM_CRYPTO_BAD 0x02
55 /* these defines are for each of the C12.22 services */
56 #define C1222_CMD_IDENTIFY 0x20
57 #define C1222_CMD_TERMINATE 0x21
58 #define C1222_CMD_DISCONNECT 0x22
59 #define C1222_CMD_FULL_READ 0x30
60 #define C1222_CMD_DEFAULT_READ 0x3E
61 #define C1222_CMD_PARTIAL_READ_OFFSET 0x3F
62 #define C1222_CMD_FULL_WRITE 0x40
63 #define C1222_CMD_DEFAULT_WRITE 0x4E
64 #define C1222_CMD_PARTIAL_WRITE_OFFSET 0x4F
65 #define C1222_CMD_LOGON 0x50
66 #define C1222_CMD_SECURITY 0x51
67 #define C1222_CMD_LOGOFF 0x52
68 #define C1222_CMD_AUTHENTICATE 0x53
69 #define C1222_CMD_NEGOTIATE 0x60
70 #define C1222_CMD_WAIT 0x70
71 #define C1222_CMD_TIMING_SETUP 0x71
73 void proto_register_c1222(void);
75 static dissector_handle_t c1222_handle
;
76 static dissector_handle_t c1222_udp_handle
;
78 /* Initialize the protocol and registered fields */
79 static int proto_c1222
;
81 static int hf_c1222_MESSAGE_PDU
; /* MESSAGE */
82 static int hf_c1222_aSO_context
; /* ASO_qualifier */
83 static int hf_c1222_called_AP_title
; /* Called_AP_title */
84 static int hf_c1222_called_AP_invocation_id
; /* Called_AP_invocation_id */
85 static int hf_c1222_calling_AP_title
; /* Calling_AP_title */
86 static int hf_c1222_calling_AE_qualifier
; /* Calling_AE_qualifier */
87 static int hf_c1222_calling_AP_invocation_id
; /* Calling_AP_invocation_id */
88 static int hf_c1222_mechanism_name
; /* Mechanism_name */
89 static int hf_c1222_calling_authentication_value
; /* Calling_authentication_value */
90 static int hf_c1222_user_information
; /* User_information */
91 static int hf_c1222_called_ap_title_abs
; /* OBJECT_IDENTIFIER */
92 static int hf_c1222_called_ap_title_rel
; /* RELATIVE_OID */
93 static int hf_c1222_calling_ap_title_abs
; /* OBJECT_IDENTIFIER */
94 static int hf_c1222_calling_ap_title_rel
; /* RELATIVE_OID */
95 static int hf_c1222_calling_authentication_value_indirect
; /* INTEGER */
96 static int hf_c1222_calling_authentication_value_encoding
; /* Authentication_value_encoding */
97 static int hf_c1222_calling_authentication_value_single_asn1
; /* Calling_authentication_value_single_asn1 */
98 static int hf_c1222_calling_authentication_value_octet_aligned
; /* OCTET_STRING */
99 static int hf_c1222_calling_authentication_value_c1222
; /* Calling_authentication_value_c1222 */
100 static int hf_c1222_calling_authentication_value_c1221
; /* Calling_authentication_value_c1221 */
101 static int hf_c1222_key_id_element
; /* Key_id_element */
102 static int hf_c1222_iv_element
; /* Iv_element */
103 static int hf_c1222_c1221_auth_identification
; /* OCTET_STRING_SIZE_CONSTR001 */
104 static int hf_c1222_c1221_auth_request
; /* OCTET_STRING_SIZE_1_255 */
105 static int hf_c1222_c1221_auth_response
; /* OCTET_STRING_SIZE_CONSTR002 */
106 /* These are the EPSEM pieces */
107 /* first, the flag components */
108 static int hf_c1222_epsem_flags
;
109 static int hf_c1222_epsem_flags_reserved
;
110 static int hf_c1222_epsem_flags_recovery
;
111 static int hf_c1222_epsem_flags_proxy
;
112 static int hf_c1222_epsem_flags_ed_class
;
113 static int hf_c1222_epsem_flags_security_modes
;
114 static int hf_c1222_epsem_flags_response_control
;
115 /* and the structure of the flag components */
116 static int * const c1222_flags
[] = {
117 &hf_c1222_epsem_flags_reserved
,
118 &hf_c1222_epsem_flags_recovery
,
119 &hf_c1222_epsem_flags_proxy
,
120 &hf_c1222_epsem_flags_ed_class
,
121 &hf_c1222_epsem_flags_security_modes
,
122 &hf_c1222_epsem_flags_response_control
,
125 /* next the optional ed_class */
126 static int hf_c1222_epsem_ed_class
;
127 /* now the aggregate epsem */
128 static int hf_c1222_epsem_total
;
129 /* generic command */
130 static int hf_c1222_cmd
;
131 static int hf_c1222_err
;
132 static int hf_c1222_data
;
133 /* individual epsem fields */
134 static int hf_c1222_logon_id
;
135 static int hf_c1222_logon_user
;
136 static int hf_c1222_security_password
;
137 static int hf_c1222_auth_len
;
138 static int hf_c1222_auth_data
;
139 static int hf_c1222_read_table
;
140 static int hf_c1222_read_offset
;
141 static int hf_c1222_read_count
;
142 static int hf_c1222_write_table
;
143 static int hf_c1222_write_offset
;
144 static int hf_c1222_write_size
;
145 static int hf_c1222_write_data
;
146 static int hf_c1222_procedure_response
;
147 static int hf_c1222_procedure_mfg
;
148 static int hf_c1222_procedure_num
;
149 static int hf_c1222_procedure_sequence
;
150 static int hf_c1222_write_chksum
;
151 static int hf_c1222_write_chksum_status
;
152 static int hf_c1222_wait_secs
;
153 static int hf_c1222_neg_pkt_size
;
154 static int hf_c1222_neg_nbr_pkts
;
155 static int hf_c1222_timing_setup_traffic
;
156 static int hf_c1222_timing_setup_inter_char
;
157 static int hf_c1222_timing_setup_resp_to
;
158 static int hf_c1222_timing_setup_nbr_retries
;
161 static int hf_c1222_epsem_mac
;
163 /* crypto result flags */
164 static int hf_c1222_epsem_crypto_good
;
165 static int hf_c1222_epsem_crypto_bad
;
167 /* Initialize the subtree pointers */
168 static int ett_c1222
;
169 static int ett_c1222_epsem
;
170 static int ett_c1222_flags
;
171 static int ett_c1222_crypto
;
172 static int ett_c1222_cmd
;
174 /* these pointers are for the header elements that may be needed to verify the crypto */
175 static uint8_t *aSO_context
;
176 static uint8_t *called_AP_title
;
177 static uint8_t *called_AP_invocation_id
;
178 static uint8_t *calling_AE_qualifier
;
179 static uint8_t *calling_AP_invocation_id
;
180 static uint8_t *mechanism_name
;
181 static uint8_t *calling_authentication_value
;
182 static uint8_t *user_information
;
183 static uint8_t *calling_AP_title
;
184 static uint8_t *key_id_element
;
185 static uint8_t *iv_element
;
187 /* these are the related lengths */
188 static uint32_t aSO_context_len
;
189 static uint32_t called_AP_title_len
;
190 static uint32_t called_AP_invocation_id_len
;
191 static uint32_t calling_AE_qualifier_len
;
192 static uint32_t calling_AP_invocation_id_len
;
193 static uint32_t mechanism_name_len
;
194 static uint32_t calling_authentication_value_len
;
195 static uint32_t user_information_len
;
196 static uint32_t calling_AP_title_len
;
197 static uint32_t key_id_element_len
;
198 static uint32_t iv_element_len
;
200 /* these are the related allocation sizes (which might be different from the lengths) */
201 static uint32_t aSO_context_allocated
;
202 static uint32_t called_AP_title_allocated
;
203 static uint32_t called_AP_invocation_id_allocated
;
204 static uint32_t calling_AE_qualifier_allocated
;
205 static uint32_t calling_AP_invocation_id_allocated
;
206 static uint32_t mechanism_name_allocated
;
207 static uint32_t calling_authentication_value_allocated
;
208 static uint32_t user_information_allocated
;
209 static uint32_t calling_AP_title_allocated
;
210 static uint32_t key_id_element_allocated
;
211 static uint32_t iv_element_allocated
;
213 static int ett_c1222_MESSAGE_U
;
214 static int ett_c1222_Called_AP_title
;
215 static int ett_c1222_Calling_AP_title
;
216 static int ett_c1222_Calling_authentication_value_U
;
217 static int ett_c1222_Authentication_value_encoding
;
218 static int ett_c1222_Calling_authentication_value_single_asn1
;
219 static int ett_c1222_Calling_authentication_value_c1222_U
;
220 static int ett_c1222_Calling_authentication_value_c1221_U
;
222 static expert_field ei_c1222_command_truncated
;
223 static expert_field ei_c1222_bad_checksum
;
224 static expert_field ei_c1222_epsem_missing
;
225 static expert_field ei_c1222_epsem_failed_authentication
;
226 static expert_field ei_c1222_epsem_not_decrypted
;
227 static expert_field ei_c1222_ed_class_missing
;
228 static expert_field ei_c1222_epsem_ber_length_error
;
229 static expert_field ei_c1222_epsem_field_length_error
;
230 static expert_field ei_c1222_mac_missing
;
233 static bool c1222_desegment
= true;
234 static bool c1222_decrypt
= true;
235 static bool c1222_big_endian
;
236 static const char *c1222_baseoid_str
;
237 static uint8_t *c1222_baseoid
;
238 static unsigned c1222_baseoid_len
;
240 /*------------------------------
242 *------------------------------
244 static const value_string c1222_security_modes
[] = {
245 { 0x00, "Cleartext"},
246 { 0x01, "Cleartext with authentication"},
247 { 0x02, "Ciphertext with authentication"},
251 static const value_string c1222_response_control
[] = {
252 { 0x00, "Always respond"},
253 { 0x01, "Respond on exception"},
254 { 0x02, "Never respond"},
258 static const value_string tableflags
[] = {
261 { 0x10, "Pending ST" },
262 { 0x18, "Pending MT" },
264 { 0x30, "Pending UDT" },
268 static const value_string procflags
[] = {
274 static const value_string c1222_proc_response_control
[] = {
275 { 0x00, "Post response in ST-8 on completion" },
276 { 0x01, "Post response in ST-8 on exception" },
277 { 0x02, "Do not post response in ST-8" },
278 { 0x03, "Post response in ST-8 now, and on completion" },
282 static const value_string commandnames
[] = {
283 /* error codes are in the range 0x00 - 0x1f inclusive */
286 { 0x02, "Service Not Supported" },
287 { 0x03, "Insufficient Security Clearance" },
288 { 0x04, "Operation Not Possible" },
289 { 0x05, "Inappropriate Action Requested" },
290 { 0x06, "Device Busy" },
291 { 0x07, "Data Not Ready" },
292 { 0x08, "Data Locked" },
293 { 0x09, "Renegotiate Request" },
294 { 0x0A, "Invalid Service Sequence State" },
295 { 0x0B, "Security Mechanism Error" },
296 { 0x0C, "Unknown Application Title" },
297 { 0x0D, "Network Time-out" },
298 { 0x0E, "Network Not Reachable" },
299 { 0x0F, "Request Too Large" },
300 { 0x10, "Response Too Large" },
301 { 0x11, "Segmentation Not Possible" },
302 { 0x12, "Segmentation Error" },
303 /* commands are in the range 0x20 - 0x7f inclusive */
304 {C1222_CMD_IDENTIFY
, "Identify" },
305 {C1222_CMD_TERMINATE
, "Terminate" },
306 {C1222_CMD_DISCONNECT
, "Disconnect" },
307 {C1222_CMD_FULL_READ
, "Full Read" },
308 {C1222_CMD_DEFAULT_READ
, "Default Read" },
309 {C1222_CMD_PARTIAL_READ_OFFSET
, "Partial Read Offset" },
310 {C1222_CMD_FULL_WRITE
, "Full Write" },
311 {C1222_CMD_DEFAULT_WRITE
, "Default Write" },
312 {C1222_CMD_PARTIAL_WRITE_OFFSET
, "Partial Write Offset" },
313 {C1222_CMD_LOGON
, "Logon" },
314 {C1222_CMD_SECURITY
, "Security" },
315 {C1222_CMD_LOGOFF
, "Logoff" },
316 {C1222_CMD_AUTHENTICATE
, "Authenticate" },
317 {C1222_CMD_NEGOTIATE
, "Negotiate" },
318 {C1222_CMD_NEGOTIATE
| 0x1, "Negotiate w/ 1 Baud Rate" },
319 {C1222_CMD_NEGOTIATE
| 0x2, "Negotiate w/ 2 Baud Rates" },
320 {C1222_CMD_NEGOTIATE
| 0x3, "Negotiate w/ 3 Baud Rates" },
321 {C1222_CMD_NEGOTIATE
| 0x4, "Negotiate w/ 4 Baud Rates" },
322 {C1222_CMD_NEGOTIATE
| 0x5, "Negotiate w/ 5 Baud Rates" },
323 {C1222_CMD_NEGOTIATE
| 0x6, "Negotiate w/ 6 Baud Rates" },
324 {C1222_CMD_NEGOTIATE
| 0x7, "Negotiate w/ 7 Baud Rates" },
325 {C1222_CMD_NEGOTIATE
| 0x8, "Negotiate w/ 8 Baud Rates" },
326 {C1222_CMD_NEGOTIATE
| 0x9, "Negotiate w/ 9 Baud Rates" },
327 {C1222_CMD_NEGOTIATE
| 0xA, "Negotiate w/ 10 Baud Rates" },
328 {C1222_CMD_NEGOTIATE
| 0xB, "Negotiate w/ 11 Baud Rates" },
329 {C1222_CMD_WAIT
, "Wait" },
330 {C1222_CMD_TIMING_SETUP
, "Timing Setup" },
334 /* these are for the key tables */
335 typedef struct _c1222_uat_data
{
341 UAT_HEX_CB_DEF(c1222_users
, keynum
, c1222_uat_data_t
)
342 UAT_BUFFER_CB_DEF(c1222_users
, key
, c1222_uat_data_t
, key
, keylen
)
344 static c1222_uat_data_t
*c1222_uat_data
;
345 static unsigned num_c1222_uat_data
;
346 static uat_t
*c1222_uat
;
348 /* these macros ares used to populate fields needed to verify crypto */
349 #define FILL_START int length, start_offset = offset;
350 #define FILL_TABLE(fieldname) \
351 length = offset - start_offset; \
352 fieldname = (uint8_t *)tvb_memdup(actx->pinfo->pool, tvb, start_offset, length); \
353 fieldname##_len = length; \
354 fieldname##_allocated = length;
355 #define FILL_TABLE_TRUNCATE(fieldname, len) \
356 length = 1 + 2*(offset - start_offset); \
357 fieldname = (uint8_t *)tvb_memdup(actx->pinfo->pool, tvb, start_offset, length); \
358 fieldname##_len = len; \
359 fieldname##_allocated = length;
360 #define FILL_TABLE_APTITLE(fieldname) \
361 length = offset - start_offset; \
362 switch (tvb_get_uint8(tvb, start_offset)) { \
363 case 0x80: /* relative OID */ \
364 tvb_ensure_bytes_exist(tvb, start_offset, length); \
365 fieldname##_len = length + c1222_baseoid_len; \
366 fieldname = (uint8_t *)wmem_alloc(actx->pinfo->pool, fieldname##_len); \
367 fieldname##_allocated = fieldname##_len; \
368 fieldname[0] = 0x06; /* create absolute OID tag */ \
369 fieldname[1] = (fieldname##_len - 2) & 0xff; \
370 memcpy(&(fieldname[2]), c1222_baseoid, c1222_baseoid_len); \
371 tvb_memcpy(tvb, &(fieldname[c1222_baseoid_len+2]), start_offset+2, length-2); \
373 case 0x06: /* absolute OID */ \
375 fieldname = (uint8_t *)tvb_memdup(actx->pinfo->pool, tvb, start_offset, length); \
376 fieldname##_len = length; \
377 fieldname##_allocated = length; \
381 /*------------------------------
382 * Function Prototypes
383 *------------------------------
385 void proto_reg_handoff_c1222(void);
388 /*------------------------------
390 *------------------------------
394 * Calculates simple one's complement checksum.
396 * \param tvb pointer to tvbuff containing data to be checksummed
397 * \param offset offset within tvbuff to beginning of data
398 * \param len length of data to be checksummed
399 * \returns calculated checksum
402 c1222_cksum(tvbuff_t
*tvb
, int offset
, int len
)
405 for (sum
= 0; len
; offset
++, len
--)
406 sum
+= tvb_get_uint8(tvb
, offset
);
410 * Dissects C12.22 packet in detail (with a tree).
412 * \param tvb input buffer containing packet to be dissected
413 * \param pinfo the packet info of the current data
414 * \param tree the tree to append this item to
415 * \param length length of data
416 * \param offset the offset in the tvb
419 parse_c1222_detailed(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int cmd
, uint32_t *length
, int *offset
)
421 uint16_t user_id
= 0;
422 const uint8_t *user_name
= NULL
;
423 const uint8_t *password
= NULL
;
424 uint8_t auth_len
= 0;
425 char *auth_req
= NULL
;
427 uint16_t tblsize
= 0;
428 uint16_t calcsum
= 0;
429 uint8_t wait_seconds
= 0;
430 uint8_t proc_seq
= 0;
432 uint16_t packet_size
;
433 uint16_t procedure_num
= 0;
435 /* timing setup parameters */
441 /* special case to simplify handling of Negotiate service */
442 if ((cmd
& 0xF0) == C1222_CMD_NEGOTIATE
) {
443 numrates
= cmd
& 0x0F;
444 cmd
= C1222_CMD_NEGOTIATE
;
446 proto_tree_add_uint(tree
, cmd
>= 0x20 ? hf_c1222_cmd
: hf_c1222_err
, tvb
, *offset
, 1, cmd
);
450 case C1222_CMD_LOGON
:
452 user_id
= tvb_get_ntohs(tvb
, *offset
);
453 proto_tree_add_uint(tree
, hf_c1222_logon_id
, tvb
, *offset
, 2, user_id
);
455 proto_tree_add_item_ret_string(tree
, hf_c1222_logon_user
, tvb
, *offset
, 10, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &user_name
);
458 proto_item_set_text(tree
, "C12.22 EPSEM: %s (id %d, user \"%s\")",
459 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), user_id
, user_name
);
461 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 LOGON command truncated");
464 case C1222_CMD_SECURITY
:
466 proto_tree_add_item_ret_string(tree
, hf_c1222_security_password
, tvb
, *offset
, 20, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &password
);
470 user_id
= tvb_get_ntohs(tvb
, *offset
);
471 proto_tree_add_uint(tree
, hf_c1222_logon_id
, tvb
, *offset
, 2, user_id
);
474 proto_item_set_text(tree
, "C12.22 EPSEM: %s (password \"%s\", id %d)",
475 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), password
, user_id
);
477 proto_item_set_text(tree
, "C12.22 EPSEM: %s (password \"%s\")",
478 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), password
);
481 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 SECURITY command truncated");
484 case C1222_CMD_AUTHENTICATE
:
486 auth_len
= tvb_get_uint8(tvb
, *offset
);
487 proto_tree_add_uint(tree
, hf_c1222_auth_len
, tvb
, *offset
, 1, auth_len
);
489 if (*length
>= auth_len
) {
490 auth_req
= tvb_bytes_to_str(pinfo
->pool
, tvb
, *offset
, auth_len
);
491 proto_tree_add_item(tree
, hf_c1222_auth_data
, tvb
, *offset
, auth_len
, ENC_NA
);
493 *length
-= auth_len
+ 1;
494 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%d bytes: %s)",
495 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), auth_len
, auth_req
);
497 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 AUTHENTICATE command truncated");
500 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 AUTHENTICATE command truncated");
503 case C1222_CMD_FULL_READ
:
505 table
= tvb_get_ntohs(tvb
, *offset
);
506 proto_tree_add_uint(tree
, hf_c1222_read_table
, tvb
, *offset
, 2, table
);
507 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%s-%d)",
508 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"),
509 val_to_str((table
>> 8) & 0xF8, tableflags
,"Unknown (0x%04x)"), table
& 0x7FF);
513 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 READ command truncated");
516 case C1222_CMD_PARTIAL_READ_OFFSET
:
518 table
= tvb_get_ntohs(tvb
, *offset
);
519 proto_tree_add_uint(tree
, hf_c1222_read_table
, tvb
, *offset
, 2, table
);
522 proto_tree_add_item(tree
, hf_c1222_read_offset
, tvb
, *offset
, 3, ENC_BIG_ENDIAN
);
525 proto_tree_add_item(tree
, hf_c1222_read_count
, tvb
, *offset
, 2, ENC_BIG_ENDIAN
);
528 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%s-%d)",
529 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"),
530 val_to_str((table
>> 8) & 0xF8, tableflags
,"Unknown (0x%04x)"), table
& 0x7FF);
532 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 READ command truncated");
535 case C1222_CMD_FULL_WRITE
:
537 table
= tvb_get_ntohs(tvb
, *offset
);
538 proto_tree_add_uint(tree
, hf_c1222_write_table
, tvb
, *offset
, 2, table
);
541 tblsize
= tvb_get_ntohs(tvb
, *offset
);
542 proto_tree_add_uint(tree
, hf_c1222_write_size
, tvb
, *offset
, 2, tblsize
);
545 if (*length
>= tblsize
+1U) {
546 if (table
== 7) {/* is it a procedure call? */
547 procedure_num
= tvb_get_uint16(tvb
, *offset
, c1222_big_endian
? ENC_BIG_ENDIAN
: ENC_LITTLE_ENDIAN
);
548 proto_tree_add_uint(tree
, hf_c1222_procedure_response
, tvb
, *offset
, 2, procedure_num
);
549 proto_tree_add_uint(tree
, hf_c1222_procedure_mfg
, tvb
, *offset
, 2, procedure_num
);
550 proto_tree_add_uint(tree
, hf_c1222_procedure_num
, tvb
, *offset
, 2, procedure_num
);
553 proc_seq
= tvb_get_uint8(tvb
, *offset
);
554 proto_tree_add_uint(tree
, hf_c1222_procedure_sequence
, tvb
, *offset
, 1, proc_seq
);
559 proto_tree_add_item(tree
, hf_c1222_write_data
, tvb
, *offset
, tblsize
, ENC_NA
);
562 if (table
== 7) {/* is it a procedure call? */
563 calcsum
= c1222_cksum(tvb
, (*offset
)-tblsize
-3, tblsize
+3);
565 calcsum
= c1222_cksum(tvb
, (*offset
)-tblsize
, tblsize
);
567 proto_tree_add_checksum(tree
, tvb
, *offset
, hf_c1222_write_chksum
, hf_c1222_write_chksum_status
,
568 &ei_c1222_bad_checksum
, pinfo
, calcsum
, ENC_NA
, PROTO_CHECKSUM_VERIFY
);
570 if (table
== 7) {/* is it a procedure call? */
571 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%s-%d, %s-%d)",
572 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"),
573 val_to_str((table
>> 8) & 0xF8, tableflags
,"Unknown (0x%04x)"), table
& 0x7FF,
574 val_to_str((procedure_num
>> 8) & 0x08, procflags
,"Unknown (0x%04x)"), procedure_num
& 0x7FF);
576 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%s-%d)",
577 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"),
578 val_to_str((table
>> 8) & 0xF8, tableflags
,"Unknown (0x%04x)"), table
& 0x7FF);
583 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 WRITE command truncated");
586 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 WRITE command truncated");
589 case C1222_CMD_PARTIAL_WRITE_OFFSET
:
591 table
= tvb_get_ntohs(tvb
, *offset
);
592 proto_tree_add_uint(tree
, hf_c1222_write_table
, tvb
, *offset
, 2, table
);
595 proto_tree_add_item(tree
, hf_c1222_write_offset
, tvb
, *offset
, 3, ENC_BIG_ENDIAN
);
598 tblsize
= tvb_get_ntohs(tvb
, *offset
);
599 proto_tree_add_uint(tree
, hf_c1222_write_size
, tvb
, *offset
, 2, tblsize
);
602 if (*length
>= tblsize
+1U) {
603 proto_tree_add_item(tree
, hf_c1222_write_data
, tvb
, *offset
, tblsize
, ENC_NA
);
606 calcsum
= c1222_cksum(tvb
, (*offset
)-tblsize
, tblsize
);
607 proto_tree_add_checksum(tree
, tvb
, *offset
, hf_c1222_write_chksum
, hf_c1222_write_chksum_status
,
608 &ei_c1222_bad_checksum
, pinfo
, calcsum
, ENC_NA
, PROTO_CHECKSUM_VERIFY
);
609 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%s-%d)",
610 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"),
611 val_to_str((table
>> 8) & 0xF8, tableflags
,"Unknown (0x%04x)"), table
& 0x7FF);
615 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 WRITE command truncated");
618 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 WRITE command truncated");
623 wait_seconds
= tvb_get_uint8(tvb
, *offset
);
624 proto_tree_add_uint(tree
, hf_c1222_wait_secs
, tvb
, *offset
, 1, wait_seconds
);
627 proto_item_set_text(tree
, "C12.22 EPSEM: %s (%d seconds)",
628 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), wait_seconds
);
630 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 WAIT command truncated");
633 case C1222_CMD_NEGOTIATE
:
635 packet_size
= tvb_get_ntohs(tvb
, *offset
);
636 proto_tree_add_uint(tree
, hf_c1222_neg_pkt_size
, tvb
, *offset
, 2, packet_size
);
639 nbr_packet
= tvb_get_uint8(tvb
, *offset
);
640 proto_tree_add_uint(tree
, hf_c1222_neg_nbr_pkts
, tvb
, *offset
, 1, nbr_packet
);
643 proto_item_set_text(tree
, "C12.22 EPSEM: %s (pkt size %d, num pkts %d, with %d baud rates)",
644 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), packet_size
, nbr_packet
, numrates
);
646 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 NEGOTIATE command truncated");
649 case C1222_CMD_TIMING_SETUP
:
651 traffic
= tvb_get_uint8(tvb
, *offset
);
652 proto_tree_add_uint(tree
, hf_c1222_timing_setup_traffic
, tvb
, *offset
, 1, traffic
);
655 inter_char
= tvb_get_uint8(tvb
, *offset
);
656 proto_tree_add_uint(tree
, hf_c1222_timing_setup_inter_char
, tvb
, *offset
, 1, inter_char
);
659 resp_to
= tvb_get_uint8(tvb
, *offset
);
660 proto_tree_add_uint(tree
, hf_c1222_timing_setup_resp_to
, tvb
, *offset
, 1, resp_to
);
663 nbr_retries
= tvb_get_uint8(tvb
, *offset
);
664 proto_tree_add_uint(tree
, hf_c1222_timing_setup_nbr_retries
, tvb
, *offset
, 1, nbr_retries
);
667 proto_item_set_text(tree
, "C12.22 EPSEM: %s (traffic to %d s, inter-char to %d s, response to %d s, %d retries)",
668 val_to_str(cmd
,commandnames
,"Unknown (0x%02x)"), traffic
, inter_char
, resp_to
, nbr_retries
);
670 expert_add_info_format(pinfo
, tree
, &ei_c1222_command_truncated
, "C12.22 NEGOTIATE command truncated");
675 /* don't do anything */
676 proto_item_set_text(tree
, "C12.22 EPSEM: %s", val_to_str(cmd
, commandnames
, "Unknown (0x%02x)"));
678 proto_tree_add_item(tree
, hf_c1222_data
, tvb
, *offset
, *length
, ENC_NA
);
684 typedef struct tagTOP_ELEMENT_CONTROL
686 /* true if this tag is required */
688 /* true if we must truncate this tag */
690 /* actual hex value of the tag we're seeking */
692 /* if true, add tag and length before copying */
694 /* pointer to pointer to memory copy of element */
696 /* pointer to element length */
698 /* pointer to element allocated size */
700 } TOP_ELEMENT_CONTROL
;
702 static const TOP_ELEMENT_CONTROL canonifyTable
[] = {
703 { false, false, 0xA1, true, &aSO_context
, &aSO_context_len
, &aSO_context_allocated
},
704 { true , false, 0xA2, true, &called_AP_title
, &called_AP_title_len
, &called_AP_title_allocated
},
705 { false, false, 0xA4, true, &called_AP_invocation_id
, &called_AP_invocation_id_len
, &called_AP_invocation_id_allocated
},
706 { false, false, 0xA7, true, &calling_AE_qualifier
, &calling_AE_qualifier_len
, &calling_AE_qualifier_allocated
},
707 { true, false, 0xA8, true, &calling_AP_invocation_id
, &calling_AP_invocation_id_len
, &calling_AP_invocation_id_allocated
},
708 { false, false, 0x8B, true, &mechanism_name
, &mechanism_name_len
, &mechanism_name_allocated
},
709 { false, false, 0xAC, true, &calling_authentication_value
, &calling_authentication_value_len
, &calling_authentication_value_allocated
},
710 { true , true , 0xBE, true, &user_information
, &user_information_len
, &user_information_allocated
},
711 { false, false, 0xA6, true, &calling_AP_title
, &calling_AP_title_len
, &calling_AP_title_allocated
},
712 { false, false, 0xAC, false, &key_id_element
, &key_id_element_len
, &key_id_element_allocated
},
713 { false, false, 0xAC, false, &iv_element
, &iv_element_len
, &iv_element_allocated
},
714 { false, false, 0x0, true, NULL
, NULL
, NULL
}
720 const TOP_ELEMENT_CONTROL
*t
= canonifyTable
;
722 for (t
= canonifyTable
; t
->element
!= NULL
; t
++) {
724 *(t
->element
) = NULL
;
729 * Calculates the size of the passed number n as encoded as a BER length field.
731 * \param n is the length value to be BER encoded
732 * \returns the sized of the encoding
735 get_ber_len_size(uint32_t n
)
740 if (n
> 0xffff) len
++;
741 if (n
> 0xffffff) len
++;
745 * Encodes the passed value n as a BER-encoded length at puts it in memory.
747 * \param ptr points to the buffer to be written
748 * \param n is the length to be BER encoded
749 * \param maxsize is the maximum number of bytes we're allowed to write
750 * \returns length of encoded value in bytes
753 encode_ber_len(uint8_t *ptr
, uint32_t n
, int maxsize
)
755 int len
= get_ber_len_size(n
);
756 if (len
> maxsize
) return 0;
760 *ptr
= (len
-1) | 0x80;
761 for (ptr
+= len
-1; n
; n
>>= 8)
769 c1222_uat_data_copy_cb(void *dest
, const void *source
, size_t len _U_
)
771 const c1222_uat_data_t
* o
= (const c1222_uat_data_t
*)source
;
772 c1222_uat_data_t
* d
= (c1222_uat_data_t
*)dest
;
774 d
->keynum
= o
->keynum
;
775 d
->keylen
= o
->keylen
;
776 d
->key
= (unsigned char *)g_memdup2(o
->key
, o
->keylen
);
782 * Checks a new encryption table item for validity.
784 * \param n points to the new record
785 * \param err is updated to point to an error string if needed
786 * \return false if error; true otherwise
789 c1222_uat_data_update_cb(void* n
, char** err
)
791 c1222_uat_data_t
* new_rec
= (c1222_uat_data_t
*)n
;
793 if (new_rec
->keynum
> 0xff) {
794 *err
= g_strdup("Invalid key number; must be less than 256");
797 if (new_rec
->keylen
!= EAX_SIZEOF_KEY
) {
798 *err
= g_strdup("Invalid key size; must be 16 bytes");
805 c1222_uat_data_free_cb(void *r
)
807 c1222_uat_data_t
*rec
= (c1222_uat_data_t
*)r
;
812 * Canonifies header fields in preparation for authenticating and/or decrypting the packet.
814 * \param buff points to the allocated canonization buffer
815 * \param offset points to start of unallocated space in buffer and
816 is updated as we put bytes into buffer
817 * \param buffsize total size of allocated buffer
818 * \return false if element is required and not present; otherwise true
821 canonify_unencrypted_header(unsigned char *buff
, uint32_t *offset
, uint32_t buffsize
)
823 const TOP_ELEMENT_CONTROL
*t
= canonifyTable
;
824 uint32_t len
, allocated
;
826 for (t
= canonifyTable
; t
->element
!= NULL
; t
++)
829 allocated
= *(t
->allocated
);
830 if (t
->required
&& *(t
->element
) == NULL
)
832 if (*(t
->element
) != NULL
) {
834 /* recreate original tag and length */
835 buff
[(*offset
)++] = t
->tag
;
836 (*offset
) += encode_ber_len(&buff
[*offset
], len
, 4);
839 len
= 3+2*get_ber_len_size(len
);
841 /* bail out if the cannonization buffer is too small */
842 /* this should never happen! */
843 if (buffsize
< *offset
+ len
) {
846 /* bail out if our we're trying to read past the end of our element */
847 /* the network is always hostile */
848 if (allocated
< len
) {
851 memcpy(&buff
[*offset
], *(t
->element
), len
);
854 *(t
->element
) = NULL
;
862 * Looks up the required key in the key table.
864 * \param keybuff is updated with a copy of the key data if successful lookup.
865 * \param keyid is the ID number of the desired key
866 * \returns true if key was found; otherwise false
869 keylookup(uint8_t *keybuff
, uint8_t keyid
)
873 if (c1222_uat_data
== NULL
)
875 for (i
= 0; i
< num_c1222_uat_data
; i
++) {
876 if (c1222_uat_data
[i
].keynum
== keyid
) {
877 memcpy(keybuff
, c1222_uat_data
[i
].key
, EAX_SIZEOF_KEY
);
885 * Authenticates and decrypts the passed packet.
887 * \param buffer points to a memory copy of the packet to be authenticated/decrypted
888 * and contains the decrypted value on successful return.
889 * \param length lenth of input packet
890 * \param decrypt true if packet is to be authenticated and decrypted; false if authentication only is requested
891 * \returns true if the requested operation was successful; otherwise false
894 decrypt_packet(unsigned char *buffer
, uint32_t length
, bool decrypt
)
896 #define CANONBUFFSIZE 300U
897 unsigned char canonbuff
[CANONBUFFSIZE
];
898 uint8_t c1222_key
[EAX_SIZEOF_KEY
];
899 unsigned char key_id
= 0;
903 /* must be at least 4 bytes long to include the MAC */
906 if (key_id_element
!= NULL
)
907 key_id
= key_id_element
[0];
908 /* extract unencrypted header information */
909 if (!canonify_unencrypted_header(canonbuff
, &offset
, CANONBUFFSIZE
))
911 /* decrypt and authenticate in place */
912 /* PARAMETERS: pN : Pointer to ClearText (Input, Canonified form). */
913 /* pK : Pointer to secret key (Input). */
914 /* pC : Pointer to CipherText (Input/Output). */
915 /* SizeN : Byte length of ClearText buffer. */
916 /* SizeK : Byte length of secret key. */
917 /* SizeC : Byte length of CipherText buffer. */
918 /* pMac : Four byte Message Authentication Code. */
919 /* Mode : Operating mode (See EAX_MODE_xxx). */
920 /* RETURNS: true if message has been authenticated. */
921 /* false if not authenticated, invalid Mode, or error. */
923 if (!keylookup((uint8_t *)&c1222_key
, key_id
))
925 status
= Eax_Decrypt(canonbuff
, c1222_key
, buffer
,
926 offset
, EAX_SIZEOF_KEY
, length
-4,
927 (MAC_T
*)&buffer
[length
-4],
928 decrypt
? EAX_MODE_CIPHERTEXT_AUTH
: EAX_MODE_CLEARTEXT_AUTH
);
934 * Checks to make sure that a complete, valid BER-encoded length is in the buffer.
936 * \param tvb contains the buffer to be examined
937 * \param offset is the offset within the buffer at which the BER-encoded length begins
938 * \returns true if a complete, valid BER-encoded length is in the buffer; otherwise false
941 ber_len_ok(tvbuff_t
*tvb
, int offset
)
945 if (tvb_offset_exists(tvb
, offset
)) {
946 ch
= tvb_get_uint8(tvb
, offset
);
950 } else if (tvb_offset_exists(tvb
, offset
)) {
951 ch
= tvb_get_uint8(tvb
, offset
);
955 } else if (tvb_offset_exists(tvb
, offset
)) {
956 ch
= tvb_get_uint8(tvb
, offset
);
960 } else if (tvb_offset_exists(tvb
, offset
)) {
961 ch
= tvb_get_uint8(tvb
, offset
);
974 * Dissects the EPSEM portion of the User-information part of a C12.22 message.
976 * \param tvb the tv buffer of the current data
977 * \param offset the offset in the tvb
978 * \param len length of data
979 * \param pinfo the packet info of the current data
980 * \param tree the tree to append this item to
983 dissect_epsem(tvbuff_t
*tvb
, int offset
, uint32_t len
, packet_info
*pinfo
, proto_tree
*tree
)
985 proto_tree
*cmd_tree
= NULL
;
986 proto_tree
*ct
= NULL
;
987 proto_tree
*crypto_tree
= NULL
;
988 proto_tree
*yt
= NULL
;
989 proto_item
*item
= NULL
;
995 unsigned char *buffer
;
996 tvbuff_t
*epsem_buffer
= NULL
;
997 bool crypto_good
= false;
998 bool crypto_bad
= false;
1000 bool encrypted
= false;
1002 if ((tvb
== NULL
) && (len
== 0)) {
1003 expert_add_info(pinfo
, tree
, &ei_c1222_epsem_missing
);
1006 /* parse the flags byte which is always unencrypted */
1007 flags
= tvb_get_uint8(tvb
, offset
);
1008 proto_tree_add_bitmask(tree
, tvb
, offset
, hf_c1222_epsem_flags
, ett_c1222_flags
, c1222_flags
, ENC_BIG_ENDIAN
);
1010 switch ((flags
& C1222_EPSEM_FLAG_SECURITY_MODE
) >> 2) {
1011 case EAX_MODE_CIPHERTEXT_AUTH
:
1012 /* mode is ciphertext with authentication */
1014 len2
= tvb_reported_length_remaining(tvb
, offset
);
1018 if (c1222_decrypt
) {
1019 buffer
= (unsigned char *)tvb_memdup(pinfo
->pool
, tvb
, offset
, len2
);
1020 if (!decrypt_packet(buffer
, len2
, true)) {
1023 epsem_buffer
= tvb_new_real_data(buffer
, len2
, len2
);
1024 tvb_set_child_real_data_tvbuff(tvb
, epsem_buffer
);
1025 add_new_data_source(pinfo
, epsem_buffer
, "Decrypted EPSEM Data");
1031 case EAX_MODE_CLEARTEXT_AUTH
:
1032 /* mode is cleartext with authentication */
1034 len2
= tvb_reported_length_remaining(tvb
, offset
);
1037 epsem_buffer
= tvb_new_subset_remaining(tvb
, offset
);
1038 buffer
= (unsigned char *)tvb_memdup(pinfo
->pool
, tvb
, offset
, len2
);
1039 if (c1222_decrypt
) {
1040 if (!decrypt_packet(buffer
, len2
, false)) {
1042 expert_add_info(pinfo
, tree
, &ei_c1222_epsem_failed_authentication
);
1049 /* it's not encrypted */
1050 epsem_buffer
= tvb_new_subset_remaining(tvb
, offset
);
1052 /* it's only encrypted if we have an undecrypted payload */
1054 proto_tree_add_item(tree
, hf_c1222_epsem_total
, tvb
, offset
, -1, ENC_NA
);
1055 expert_add_info(pinfo
, tree
, &ei_c1222_epsem_not_decrypted
);
1056 local_offset
= offset
+len2
-4;
1058 } else { /* it's not (now) encrypted */
1060 /* retrieve the ed_class if it's there */
1061 if (flags
& C1222_EPSEM_FLAG_ED_CLASS_INCLUDED
) {
1062 if (tvb_offset_exists(epsem_buffer
, local_offset
+4-1)) {
1063 proto_tree_add_item(tree
, hf_c1222_epsem_ed_class
, epsem_buffer
, local_offset
, 4, ENC_NA
);
1066 expert_add_info(pinfo
, tree
, &ei_c1222_ed_class_missing
);
1069 /* what follows are one or more <epsem-data> elements possibly followed by
1070 * a <mac>. Each <epsem-data> element is defined as <service-length><res-req>,
1071 * so we fetch such pairs until there isn't anything left (except possibly
1074 while (tvb_offset_exists(epsem_buffer
, local_offset
+(hasmac
?5:1))) {
1075 if (ber_len_ok(epsem_buffer
, local_offset
)) {
1076 local_offset
= dissect_ber_length(pinfo
, tree
, epsem_buffer
, local_offset
, (uint32_t *)&len2
, &ind
);
1078 expert_add_info(pinfo
, tree
, &ei_c1222_epsem_ber_length_error
);
1081 if (tvb_offset_exists(epsem_buffer
, local_offset
+len2
-1)) {
1082 cmd_err
= tvb_get_uint8(epsem_buffer
, local_offset
);
1083 ct
= proto_tree_add_item(tree
, hf_c1222_epsem_total
, epsem_buffer
, local_offset
, len2
, ENC_NA
);
1084 cmd_tree
= proto_item_add_subtree(ct
, ett_c1222_cmd
);
1085 parse_c1222_detailed(epsem_buffer
, pinfo
, cmd_tree
, cmd_err
, (uint32_t *)&len2
, &local_offset
);
1086 local_offset
+= len2
;
1088 expert_add_info(pinfo
, tree
, &ei_c1222_epsem_field_length_error
);
1094 if (tvb_offset_exists(epsem_buffer
, local_offset
+4-1)) {
1095 yt
= proto_tree_add_item(tree
, hf_c1222_epsem_mac
, epsem_buffer
, local_offset
, 4, ENC_NA
);
1096 /* now we have enough information to fill in the crypto subtree */
1097 crypto_tree
= proto_item_add_subtree(yt
, ett_c1222_crypto
);
1098 item
= proto_tree_add_boolean(crypto_tree
, hf_c1222_epsem_crypto_good
, tvb
, local_offset
, 4, crypto_good
);
1099 proto_item_set_generated(item
);
1100 item
= proto_tree_add_boolean(crypto_tree
, hf_c1222_epsem_crypto_bad
, tvb
, local_offset
, 4, crypto_bad
);
1101 proto_item_set_generated(item
);
1103 expert_add_info(pinfo
, tree
, &ei_c1222_mac_missing
);
1113 dissect_c1222_ASO_qualifier(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1115 offset
= dissect_ber_object_identifier(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, NULL
);
1117 FILL_TABLE(aSO_context
);
1126 dissect_c1222_OBJECT_IDENTIFIER(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1127 offset
= dissect_ber_object_identifier(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, NULL
);
1135 dissect_c1222_RELATIVE_OID(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1136 offset
= dissect_ber_relative_oid(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, NULL
);
1142 static const value_string c1222_Called_AP_title_vals
[] = {
1143 { 0, "called-ap-title-abs" },
1144 { 1, "called-ap-title-rel" },
1148 static const ber_choice_t Called_AP_title_choice
[] = {
1149 { 0, &hf_c1222_called_ap_title_abs
, BER_CLASS_UNI
, BER_UNI_TAG_OID
, BER_FLAGS_NOOWNTAG
, dissect_c1222_OBJECT_IDENTIFIER
},
1150 { 1, &hf_c1222_called_ap_title_rel
, BER_CLASS_CON
, 0, BER_FLAGS_IMPLTAG
, dissect_c1222_RELATIVE_OID
},
1151 { 0, NULL
, 0, 0, 0, NULL
}
1155 dissect_c1222_Called_AP_title(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1157 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
1158 Called_AP_title_choice
, hf_index
, ett_c1222_Called_AP_title
,
1161 FILL_TABLE_APTITLE(called_AP_title
);
1170 dissect_c1222_AP_invocation_id(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1171 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1180 dissect_c1222_Called_AP_invocation_id(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1182 offset
= dissect_c1222_AP_invocation_id(implicit_tag
, tvb
, offset
, actx
, tree
, hf_index
);
1184 FILL_TABLE(called_AP_invocation_id
);
1191 static const value_string c1222_Calling_AP_title_vals
[] = {
1192 { 0, "calling-ap-title-abs" },
1193 { 1, "calling-ap-title-rel" },
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
}
1204 dissect_c1222_Calling_AP_title(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1206 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
1207 Calling_AP_title_choice
, hf_index
, ett_c1222_Calling_AP_title
,
1210 FILL_TABLE_APTITLE(calling_AP_title
);
1219 dissect_c1222_AE_qualifier(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1220 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1229 dissect_c1222_Calling_AE_qualifier(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1231 offset
= dissect_c1222_AE_qualifier(implicit_tag
, tvb
, offset
, actx
, tree
, hf_index
);
1233 FILL_TABLE(calling_AE_qualifier
);
1242 dissect_c1222_Calling_AP_invocation_id(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1244 offset
= dissect_c1222_AP_invocation_id(implicit_tag
, tvb
, offset
, actx
, tree
, hf_index
);
1246 FILL_TABLE(calling_AP_invocation_id
);
1255 dissect_c1222_Mechanism_name(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1257 offset
= dissect_ber_object_identifier(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
, NULL
);
1259 FILL_TABLE(mechanism_name
);
1268 dissect_c1222_INTEGER(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1269 offset
= dissect_ber_integer(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1278 dissect_c1222_Key_id_element(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1280 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1283 FILL_TABLE(key_id_element
);
1292 dissect_c1222_Iv_element(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1294 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1297 FILL_TABLE(iv_element
);
1304 static const ber_sequence_t Calling_authentication_value_c1222_U_sequence
[] = {
1305 { &hf_c1222_key_id_element
, BER_CLASS_CON
, 0, BER_FLAGS_OPTIONAL
|BER_FLAGS_IMPLTAG
, dissect_c1222_Key_id_element
},
1306 { &hf_c1222_iv_element
, BER_CLASS_CON
, 1, BER_FLAGS_OPTIONAL
|BER_FLAGS_IMPLTAG
, dissect_c1222_Iv_element
},
1307 { NULL
, 0, 0, 0, NULL
}
1311 dissect_c1222_Calling_authentication_value_c1222_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1312 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
1313 Calling_authentication_value_c1222_U_sequence
, hf_index
, ett_c1222_Calling_authentication_value_c1222_U
);
1321 dissect_c1222_Calling_authentication_value_c1222(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1322 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
1323 hf_index
, BER_CLASS_CON
, 1, true, dissect_c1222_Calling_authentication_value_c1222_U
);
1331 dissect_c1222_OCTET_STRING_SIZE_CONSTR001(bool 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_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1341 dissect_c1222_OCTET_STRING_SIZE_1_255(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1342 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1351 dissect_c1222_OCTET_STRING_SIZE_CONSTR002(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1352 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1359 static const value_string c1222_Calling_authentication_value_c1221_U_vals
[] = {
1360 { 0, "c1221-auth-identification" },
1361 { 1, "c1221-auth-request" },
1362 { 2, "c1221-auth-response" },
1366 static const ber_choice_t Calling_authentication_value_c1221_U_choice
[] = {
1367 { 0, &hf_c1222_c1221_auth_identification
, BER_CLASS_CON
, 0, BER_FLAGS_IMPLTAG
, dissect_c1222_OCTET_STRING_SIZE_CONSTR001
},
1368 { 1, &hf_c1222_c1221_auth_request
, BER_CLASS_CON
, 1, BER_FLAGS_IMPLTAG
, dissect_c1222_OCTET_STRING_SIZE_1_255
},
1369 { 2, &hf_c1222_c1221_auth_response
, BER_CLASS_CON
, 2, BER_FLAGS_IMPLTAG
, dissect_c1222_OCTET_STRING_SIZE_CONSTR002
},
1370 { 0, NULL
, 0, 0, 0, NULL
}
1374 dissect_c1222_Calling_authentication_value_c1221_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1375 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
1376 Calling_authentication_value_c1221_U_choice
, hf_index
, ett_c1222_Calling_authentication_value_c1221_U
,
1385 dissect_c1222_Calling_authentication_value_c1221(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1386 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
1387 hf_index
, BER_CLASS_CON
, 0, true, dissect_c1222_Calling_authentication_value_c1221_U
);
1393 static const value_string c1222_Calling_authentication_value_single_asn1_vals
[] = {
1394 { 1, "calling-authentication-value-c1222" },
1395 { 0, "calling-authentication-value-c1221" },
1399 static const ber_choice_t Calling_authentication_value_single_asn1_choice
[] = {
1400 { 1, &hf_c1222_calling_authentication_value_c1222
, BER_CLASS_CON
, 1, BER_FLAGS_NOOWNTAG
, dissect_c1222_Calling_authentication_value_c1222
},
1401 { 0, &hf_c1222_calling_authentication_value_c1221
, BER_CLASS_CON
, 0, BER_FLAGS_NOOWNTAG
, dissect_c1222_Calling_authentication_value_c1221
},
1402 { 0, NULL
, 0, 0, 0, NULL
}
1406 dissect_c1222_Calling_authentication_value_single_asn1(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1407 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
1408 Calling_authentication_value_single_asn1_choice
, hf_index
, ett_c1222_Calling_authentication_value_single_asn1
,
1417 dissect_c1222_OCTET_STRING(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1418 offset
= dissect_ber_octet_string(implicit_tag
, actx
, tree
, tvb
, offset
, hf_index
,
1425 static const value_string c1222_Authentication_value_encoding_vals
[] = {
1426 { 0, "calling-authentication-value-single-asn1" },
1427 { 1, "calling-authentication-value-octet-aligned" },
1431 static const ber_choice_t Authentication_value_encoding_choice
[] = {
1432 { 0, &hf_c1222_calling_authentication_value_single_asn1
, BER_CLASS_CON
, 0, 0, dissect_c1222_Calling_authentication_value_single_asn1
},
1433 { 1, &hf_c1222_calling_authentication_value_octet_aligned
, BER_CLASS_CON
, 1, BER_FLAGS_IMPLTAG
, dissect_c1222_OCTET_STRING
},
1434 { 0, NULL
, 0, 0, 0, NULL
}
1438 dissect_c1222_Authentication_value_encoding(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1439 offset
= dissect_ber_choice(actx
, tree
, tvb
, offset
,
1440 Authentication_value_encoding_choice
, hf_index
, ett_c1222_Authentication_value_encoding
,
1447 static const ber_sequence_t Calling_authentication_value_U_sequence
[] = {
1448 { &hf_c1222_calling_authentication_value_indirect
, BER_CLASS_UNI
, BER_UNI_TAG_INTEGER
, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOOWNTAG
, dissect_c1222_INTEGER
},
1449 { &hf_c1222_calling_authentication_value_encoding
, BER_CLASS_ANY
/*choice*/, -1/*choice*/, BER_FLAGS_NOOWNTAG
|BER_FLAGS_NOTCHKTAG
, dissect_c1222_Authentication_value_encoding
},
1450 { NULL
, 0, 0, 0, NULL
}
1454 dissect_c1222_Calling_authentication_value_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1455 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
1456 Calling_authentication_value_U_sequence
, hf_index
, ett_c1222_Calling_authentication_value_U
);
1464 dissect_c1222_Calling_authentication_value(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1466 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
1467 hf_index
, BER_CLASS_CON
, 2, true, dissect_c1222_Calling_authentication_value_U
);
1469 FILL_TABLE(calling_authentication_value
);
1478 dissect_c1222_User_information(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1479 int8_t end_device_class
;
1483 proto_item
*tf
= NULL
;
1484 proto_tree
*epsem_tree
= NULL
;
1487 /* get Tag and Length */
1488 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &end_device_class
, &pc
, &tag
);
1489 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
1490 FILL_TABLE_TRUNCATE(user_information
, len
+offset
-start_offset
);
1491 if (tag
== 0x8) { /* BER_TAG_EXTERNAL */
1492 offset
= dissect_ber_identifier(actx
->pinfo
, tree
, tvb
, offset
, &end_device_class
, &pc
, &tag
);
1493 offset
= dissect_ber_length(actx
->pinfo
, tree
, tvb
, offset
, &len
, &ind
);
1494 if (tag
== 0x1) { /* implicit octet string */
1495 tf
= proto_tree_add_item(tree
, hf_c1222_user_information
, tvb
, offset
, len
, ENC_NA
);
1496 epsem_tree
= proto_item_add_subtree(tf
, ett_c1222_epsem
);
1497 dissect_epsem(tvb
, offset
, len
, actx
->pinfo
, epsem_tree
);
1507 static const ber_sequence_t MESSAGE_U_sequence
[] = {
1508 { &hf_c1222_aSO_context
, BER_CLASS_CON
, 1, BER_FLAGS_OPTIONAL
, dissect_c1222_ASO_qualifier
},
1509 { &hf_c1222_called_AP_title
, BER_CLASS_CON
, 2, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOTCHKTAG
, dissect_c1222_Called_AP_title
},
1510 { &hf_c1222_called_AP_invocation_id
, BER_CLASS_CON
, 4, BER_FLAGS_OPTIONAL
, dissect_c1222_Called_AP_invocation_id
},
1511 { &hf_c1222_calling_AP_title
, BER_CLASS_CON
, 6, BER_FLAGS_OPTIONAL
|BER_FLAGS_NOTCHKTAG
, dissect_c1222_Calling_AP_title
},
1512 { &hf_c1222_calling_AE_qualifier
, BER_CLASS_CON
, 7, BER_FLAGS_OPTIONAL
, dissect_c1222_Calling_AE_qualifier
},
1513 { &hf_c1222_calling_AP_invocation_id
, BER_CLASS_CON
, 8, 0, dissect_c1222_Calling_AP_invocation_id
},
1514 { &hf_c1222_mechanism_name
, BER_CLASS_CON
, 11, BER_FLAGS_OPTIONAL
|BER_FLAGS_IMPLTAG
, dissect_c1222_Mechanism_name
},
1515 { &hf_c1222_calling_authentication_value
, BER_CLASS_CON
, 12, BER_FLAGS_OPTIONAL
, dissect_c1222_Calling_authentication_value
},
1516 { &hf_c1222_user_information
, BER_CLASS_CON
, 30, 0, dissect_c1222_User_information
},
1517 { NULL
, 0, 0, 0, NULL
}
1521 dissect_c1222_MESSAGE_U(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1522 offset
= dissect_ber_sequence(implicit_tag
, actx
, tree
, tvb
, offset
,
1523 MESSAGE_U_sequence
, hf_index
, ett_c1222_MESSAGE_U
);
1531 dissect_c1222_MESSAGE(bool implicit_tag _U_
, tvbuff_t
*tvb _U_
, int offset _U_
, asn1_ctx_t
*actx _U_
, proto_tree
*tree _U_
, int hf_index _U_
) {
1533 offset
= dissect_ber_tagged_type(implicit_tag
, actx
, tree
, tvb
, offset
,
1534 hf_index
, BER_CLASS_APP
, 0, true, dissect_c1222_MESSAGE_U
);
1542 static int dissect_MESSAGE_PDU(tvbuff_t
*tvb _U_
, packet_info
*pinfo _U_
, proto_tree
*tree _U_
, void *data _U_
) {
1544 asn1_ctx_t asn1_ctx
;
1545 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, true, pinfo
);
1546 offset
= dissect_c1222_MESSAGE(false, tvb
, offset
, &asn1_ctx
, tree
, hf_c1222_MESSAGE_PDU
);
1552 * Dissects a a full (reassembled) C12.22 message.
1554 * \param tvb the tv buffer of the current data
1555 * \param pinfo the packet info of the current data
1556 * \param tree the tree to append this item to
1559 dissect_c1222_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
1561 proto_item
*c1222_item
= NULL
;
1562 proto_tree
*c1222_tree
= NULL
;
1564 /* make entry in the Protocol column on summary display */
1565 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PNAME
);
1567 /* create the c1222 protocol tree */
1568 c1222_item
= proto_tree_add_item(tree
, proto_c1222
, tvb
, 0, -1, ENC_NA
);
1569 c1222_tree
= proto_item_add_subtree(c1222_item
, ett_c1222
);
1570 return dissect_MESSAGE_PDU(tvb
, pinfo
, c1222_tree
, NULL
);
1574 * Fetches the length of an entire C12.22 message to assist in reassembly.
1576 * \param pinfo the packet info of the current data
1577 * \param tvb the tv buffer of the current data
1578 * \param offset the offset in the tvb
1579 * \returns length of entire C12.22 message
1582 get_c1222_message_len(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
1588 orig_offset
= offset
;
1589 /* note that this assumes a Tag length of 1 which is always valid for C12.22 */
1590 offset
= dissect_ber_length(pinfo
, NULL
, tvb
, offset
+1, &length
, &ind
);
1591 return length
+(offset
- orig_offset
);
1595 * Reassembles and dissects C12.22 messages.
1597 * \param tvb the tv buffer of the current data
1598 * \param pinfo the packet info of the current data
1599 * \param tree the tree to append this item to
1602 dissect_c1222(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
1604 tcp_dissect_pdus(tvb
, pinfo
, tree
, c1222_desegment
, 5,
1605 get_c1222_message_len
, dissect_c1222_common
, data
);
1606 return tvb_captured_length(tvb
);
1609 /*--- proto_register_c1222 -------------------------------------------*/
1610 void proto_register_c1222(void) {
1612 /* List of fields */
1613 static hf_register_info hf
[] = {
1614 { &hf_c1222_epsem_flags
,
1615 { "C12.22 EPSEM Flags", "c1222.epsem.flags",
1620 { &hf_c1222_epsem_flags_reserved
,
1621 { "C12.22 Reserved Flag", "c1222.epsem.flags.reserved",
1623 NULL
, C1222_EPSEM_FLAG_RESERVED
,
1626 { &hf_c1222_epsem_flags_recovery
,
1627 { "C12.22 Recovery Flag", "c1222.epsem.flags.recovery",
1629 NULL
, C1222_EPSEM_FLAG_RECOVERY_SESSION
,
1632 { &hf_c1222_epsem_flags_proxy
,
1633 { "C12.22 Proxy Service Used Flag", "c1222.epsem.flags.proxy",
1635 NULL
, C1222_EPSEM_FLAG_PROXY_SERVICE_USED
,
1638 { &hf_c1222_epsem_flags_ed_class
,
1639 { "C12.22 ED Class Flag", "c1222.epsem.flags.ed_class",
1641 NULL
, C1222_EPSEM_FLAG_ED_CLASS_INCLUDED
,
1644 { &hf_c1222_epsem_flags_security_modes
,
1645 { "C12.22 Security Mode Flags", "c1222.epsem.flags.security",
1647 VALS(c1222_security_modes
), C1222_EPSEM_FLAG_SECURITY_MODE
,
1650 { &hf_c1222_epsem_flags_response_control
,
1651 { "C12.22 Response Control Flags", "c1222.epsem.flags.response_control",
1653 VALS(c1222_response_control
), C1222_EPSEM_FLAG_RESPONSE_CONTROL
,
1656 { &hf_c1222_epsem_ed_class
,
1657 { "C12.22 EPSEM ED Class", "c1222.epsem.edclass",
1658 FT_BYTES
, BASE_NONE
,
1662 { &hf_c1222_epsem_total
,
1663 { "C12.22 EPSEM", "c1222.epsem.data",
1664 FT_BYTES
, BASE_NONE
,
1668 { &hf_c1222_epsem_mac
,
1669 { "C12.22 EPSEM MAC", "c1222.epsem.mac",
1670 FT_BYTES
, BASE_NONE
,
1675 { "C12.22 Command", "c1222.cmd",
1677 VALS(commandnames
), 0x0,
1681 { "C12.22 Response", "c1222.err",
1683 VALS(commandnames
), 0x0,
1686 { &hf_c1222_logon_id
,
1687 { "C12.22 Logon User-Id", "c1222.logon.id",
1688 FT_UINT16
, BASE_DEC
,
1692 { &hf_c1222_logon_user
,
1693 { "C12.22 Logon User", "c1222.logon.user",
1694 FT_STRING
, BASE_NONE
,
1698 { &hf_c1222_security_password
,
1699 { "C12.22 Security Password", "c1222.security.password",
1700 FT_STRING
, BASE_NONE
,
1704 { &hf_c1222_auth_len
,
1705 { "C12.22 Authenticate Request Length", "c1222.authenticate.len",
1710 { &hf_c1222_auth_data
,
1711 { "C12.22 Authenticate Data", "c1222.authenticate.data",
1712 FT_BYTES
, BASE_NONE
,
1716 { &hf_c1222_read_table
,
1717 { "C12.22 Table", "c1222.read.table",
1718 FT_UINT16
, BASE_HEX
,
1722 { &hf_c1222_read_offset
,
1723 { "C12.22 Offset", "c1222.read.offset",
1724 FT_UINT24
, BASE_HEX
,
1728 { &hf_c1222_read_count
,
1729 { "C12.22 Count", "c1222.read.count",
1730 FT_UINT16
, BASE_DEC
,
1734 { &hf_c1222_write_table
,
1735 { "C12.22 Table", "c1222.write.table",
1736 FT_UINT16
, BASE_HEX
,
1740 { &hf_c1222_write_offset
,
1741 { "C12.22 Offset", "c1222.write.offset",
1742 FT_UINT24
, BASE_HEX
,
1746 { &hf_c1222_write_size
,
1747 { "C12.22 Table Size", "c1222.write.size",
1748 FT_UINT16
, BASE_HEX
,
1752 { &hf_c1222_write_data
,
1753 { "C12.22 Table Data", "c1222.write.data",
1754 FT_BYTES
, BASE_NONE
,
1758 { &hf_c1222_write_chksum
,
1759 { "C12.22 Table Data Checksum", "c1222.write.chksum",
1764 { &hf_c1222_write_chksum_status
,
1765 { "C12.22 Table Data Checksum Status", "c1222.write.chksum.status",
1766 FT_UINT8
, BASE_NONE
,
1767 VALS(proto_checksum_vals
), 0x0,
1770 { &hf_c1222_procedure_response
,
1771 { "C12.22 Procedure Response", "c1222.procedure.response",
1772 FT_UINT16
, BASE_DEC
,
1773 VALS(c1222_proc_response_control
), C1222_PROCEDURE_RESPONSE
,
1776 { &hf_c1222_procedure_mfg
,
1777 { "C12.22 Procedure Mfg", "c1222.procedure.mfg",
1778 FT_UINT16
, BASE_DEC
,
1779 NULL
, C1222_PROCEDURE_MFG
,
1782 { &hf_c1222_procedure_num
,
1783 { "C12.22 Procedure Number", "c1222.procedure.num",
1784 FT_UINT16
, BASE_DEC
,
1785 NULL
, C1222_PROCEDURE_NUMBER
,
1788 { &hf_c1222_procedure_sequence
,
1789 { "C12.22 Procedure Sequence Number", "c1222.procedure.sequence",
1794 { &hf_c1222_neg_pkt_size
,
1795 { "C12.22 Negotiate Packet Size", "c1222.negotiate.pktsize",
1796 FT_UINT16
, BASE_DEC
,
1800 { &hf_c1222_neg_nbr_pkts
,
1801 { "C12.22 Negotiate Number of Packets", "c1222.negotiate.numpkts",
1806 { &hf_c1222_wait_secs
,
1807 { "C12.22 Wait Seconds", "c1222.wait.seconds",
1812 { &hf_c1222_timing_setup_traffic
,
1813 { "C12.22 Timing Setup Channel Traffic Timeout", "c1222.timingsetup.traffic",
1818 { &hf_c1222_timing_setup_inter_char
,
1819 { "C12.22 Timing Setup Intercharacter Timeout", "c1222.timingsetup.interchar",
1824 { &hf_c1222_timing_setup_resp_to
,
1825 { "C12.22 Timing Setup Response Timeout", "c1222.timingsetup.respto",
1830 { &hf_c1222_timing_setup_nbr_retries
,
1831 { "C12.22 Timing Setup Number of Retries", "c1222.timingsetup.nbrretries",
1837 { "C12.22 data", "c1222.data",
1838 FT_BYTES
, BASE_NONE
,
1842 { &hf_c1222_epsem_crypto_good
,
1843 { "Crypto good", "c1222.crypto_good",
1844 FT_BOOLEAN
, BASE_NONE
,
1846 "True: crypto ok; False: doesn't match or not checked", HFILL
}
1848 { &hf_c1222_epsem_crypto_bad
,
1849 { "Crypto bad", "c1222.crypto_bad",
1850 FT_BOOLEAN
, BASE_NONE
,
1852 "True: crypto bad; False: crypto ok or not checked", HFILL
}
1854 { &hf_c1222_MESSAGE_PDU
,
1855 { "MESSAGE", "c1222.MESSAGE_element",
1856 FT_NONE
, BASE_NONE
, NULL
, 0,
1858 { &hf_c1222_aSO_context
,
1859 { "aSO-context", "c1222.aSO_context",
1860 FT_OID
, BASE_NONE
, NULL
, 0,
1861 "ASO_qualifier", HFILL
}},
1862 { &hf_c1222_called_AP_title
,
1863 { "called-AP-title", "c1222.called_AP_title",
1864 FT_UINT32
, BASE_DEC
, VALS(c1222_Called_AP_title_vals
), 0,
1866 { &hf_c1222_called_AP_invocation_id
,
1867 { "called-AP-invocation-id", "c1222.called_AP_invocation_id",
1868 FT_UINT32
, BASE_DEC
, NULL
, 0,
1870 { &hf_c1222_calling_AP_title
,
1871 { "calling-AP-title", "c1222.calling_AP_title",
1872 FT_UINT32
, BASE_DEC
, VALS(c1222_Calling_AP_title_vals
), 0,
1874 { &hf_c1222_calling_AE_qualifier
,
1875 { "calling-AE-qualifier", "c1222.calling_AE_qualifier",
1876 FT_UINT32
, BASE_DEC
, NULL
, 0,
1878 { &hf_c1222_calling_AP_invocation_id
,
1879 { "calling-AP-invocation-id", "c1222.calling_AP_invocation_id",
1880 FT_UINT32
, BASE_DEC
, NULL
, 0,
1882 { &hf_c1222_mechanism_name
,
1883 { "mechanism-name", "c1222.mechanism_name",
1884 FT_OID
, BASE_NONE
, NULL
, 0,
1886 { &hf_c1222_calling_authentication_value
,
1887 { "calling-authentication-value", "c1222.calling_authentication_value_element",
1888 FT_NONE
, BASE_NONE
, NULL
, 0,
1890 { &hf_c1222_user_information
,
1891 { "user-information", "c1222.user_information_element",
1892 FT_NONE
, BASE_NONE
, NULL
, 0,
1894 { &hf_c1222_called_ap_title_abs
,
1895 { "called-ap-title-abs", "c1222.called_ap_title_abs",
1896 FT_OID
, BASE_NONE
, NULL
, 0,
1897 "OBJECT_IDENTIFIER", HFILL
}},
1898 { &hf_c1222_called_ap_title_rel
,
1899 { "called-ap-title-rel", "c1222.called_ap_title_rel",
1900 FT_REL_OID
, BASE_NONE
, NULL
, 0,
1901 "RELATIVE_OID", HFILL
}},
1902 { &hf_c1222_calling_ap_title_abs
,
1903 { "calling-ap-title-abs", "c1222.calling_ap_title_abs",
1904 FT_OID
, BASE_NONE
, NULL
, 0,
1905 "OBJECT_IDENTIFIER", HFILL
}},
1906 { &hf_c1222_calling_ap_title_rel
,
1907 { "calling-ap-title-rel", "c1222.calling_ap_title_rel",
1908 FT_REL_OID
, BASE_NONE
, NULL
, 0,
1909 "RELATIVE_OID", HFILL
}},
1910 { &hf_c1222_calling_authentication_value_indirect
,
1911 { "calling-authentication-value-indirect", "c1222.calling_authentication_value_indirect",
1912 FT_INT32
, BASE_DEC
, NULL
, 0,
1913 "INTEGER", HFILL
}},
1914 { &hf_c1222_calling_authentication_value_encoding
,
1915 { "calling-authentication-value-encoding", "c1222.calling_authentication_value_encoding",
1916 FT_UINT32
, BASE_DEC
, VALS(c1222_Authentication_value_encoding_vals
), 0,
1917 "Authentication_value_encoding", HFILL
}},
1918 { &hf_c1222_calling_authentication_value_single_asn1
,
1919 { "calling-authentication-value-single-asn1", "c1222.calling_authentication_value_single_asn1",
1920 FT_UINT32
, BASE_DEC
, VALS(c1222_Calling_authentication_value_single_asn1_vals
), 0,
1922 { &hf_c1222_calling_authentication_value_octet_aligned
,
1923 { "calling-authentication-value-octet-aligned", "c1222.calling_authentication_value_octet_aligned",
1924 FT_BYTES
, BASE_NONE
, NULL
, 0,
1925 "OCTET_STRING", HFILL
}},
1926 { &hf_c1222_calling_authentication_value_c1222
,
1927 { "calling-authentication-value-c1222", "c1222.calling_authentication_value_c1222_element",
1928 FT_NONE
, BASE_NONE
, NULL
, 0,
1930 { &hf_c1222_calling_authentication_value_c1221
,
1931 { "calling-authentication-value-c1221", "c1222.calling_authentication_value_c1221",
1932 FT_UINT32
, BASE_DEC
, VALS(c1222_Calling_authentication_value_c1221_U_vals
), 0,
1934 { &hf_c1222_key_id_element
,
1935 { "key-id-element", "c1222.key_id_element",
1936 FT_BYTES
, BASE_NONE
, NULL
, 0,
1938 { &hf_c1222_iv_element
,
1939 { "iv-element", "c1222.iv_element",
1940 FT_BYTES
, BASE_NONE
, NULL
, 0,
1942 { &hf_c1222_c1221_auth_identification
,
1943 { "c1221-auth-identification", "c1222.c1221_auth_identification",
1944 FT_BYTES
, BASE_NONE
, NULL
, 0,
1945 "OCTET_STRING_SIZE_CONSTR001", HFILL
}},
1946 { &hf_c1222_c1221_auth_request
,
1947 { "c1221-auth-request", "c1222.c1221_auth_request",
1948 FT_BYTES
, BASE_NONE
, NULL
, 0,
1949 "OCTET_STRING_SIZE_1_255", HFILL
}},
1950 { &hf_c1222_c1221_auth_response
,
1951 { "c1221-auth-response", "c1222.c1221_auth_response",
1952 FT_BYTES
, BASE_NONE
, NULL
, 0,
1953 "OCTET_STRING_SIZE_CONSTR002", HFILL
}},
1956 /* List of subtrees */
1957 static int *ett
[] = {
1963 &ett_c1222_MESSAGE_U
,
1964 &ett_c1222_Called_AP_title
,
1965 &ett_c1222_Calling_AP_title
,
1966 &ett_c1222_Calling_authentication_value_U
,
1967 &ett_c1222_Authentication_value_encoding
,
1968 &ett_c1222_Calling_authentication_value_single_asn1
,
1969 &ett_c1222_Calling_authentication_value_c1222_U
,
1970 &ett_c1222_Calling_authentication_value_c1221_U
,
1973 static ei_register_info ei
[] = {
1974 { &ei_c1222_command_truncated
, { "c1222.command_truncated", PI_MALFORMED
, PI_ERROR
, "C12.22 command truncated", EXPFILL
}},
1975 { &ei_c1222_bad_checksum
, { "c1222.bad_checksum", PI_CHECKSUM
, PI_ERROR
, "Bad checksum", EXPFILL
}},
1976 { &ei_c1222_epsem_missing
, { "c1222.epsem.missing", PI_MALFORMED
, PI_ERROR
, "C12.22 EPSEM missing", EXPFILL
}},
1977 { &ei_c1222_epsem_failed_authentication
, { "c1222.epsem.failed_authentication", PI_SECURITY
, PI_ERROR
, "C12.22 EPSEM failed authentication", EXPFILL
}},
1978 { &ei_c1222_epsem_not_decrypted
, { "c1222.epsem.not_decrypted", PI_UNDECODED
, PI_WARN
, "C12.22 EPSEM could not be decrypted", EXPFILL
}},
1979 { &ei_c1222_ed_class_missing
, { "c1222.ed_class_missing", PI_SECURITY
, PI_ERROR
, "C12.22 ED Class missing", EXPFILL
}},
1980 { &ei_c1222_epsem_ber_length_error
, { "c1222.epsem.ber_length_error", PI_MALFORMED
, PI_ERROR
, "C12.22 EPSEM BER length error", EXPFILL
}},
1981 { &ei_c1222_epsem_field_length_error
, { "c1222.epsem.field_length_error", PI_MALFORMED
, PI_ERROR
, "C12.22 EPSEM field length error", EXPFILL
}},
1982 { &ei_c1222_mac_missing
, { "c1222.mac_missing", PI_MALFORMED
, PI_ERROR
, "C12.22 MAC missing", EXPFILL
}},
1985 expert_module_t
* expert_c1222
;
1986 module_t
*c1222_module
;
1988 static uat_field_t c1222_uat_flds
[] = {
1989 UAT_FLD_HEX(c1222_users
,keynum
,"Key ID","Key identifier in hexadecimal"),
1990 UAT_FLD_BUFFER(c1222_users
, key
, "Key", "Encryption key as 16-byte hex string"),
1994 /* Register protocol */
1995 proto_c1222
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
1996 /* Register fields and subtrees */
1997 proto_register_field_array(proto_c1222
, hf
, array_length(hf
));
1998 proto_register_subtree_array(ett
, array_length(ett
));
1999 expert_c1222
= expert_register_protocol(proto_c1222
);
2000 expert_register_field_array(expert_c1222
, ei
, array_length(ei
));
2001 /* Register dissectors */
2002 c1222_handle
= register_dissector("c1222.tcp", dissect_c1222
, proto_c1222
);
2003 c1222_udp_handle
= register_dissector("c1222.udp", dissect_c1222_common
, proto_c1222
);
2004 /* Register dissection preferences */
2005 c1222_module
= prefs_register_protocol(proto_c1222
, proto_reg_handoff_c1222
);
2006 prefs_register_bool_preference(c1222_module
, "desegment",
2007 "Reassemble all C12.22 messages spanning multiple TCP segments",
2008 "Whether the C12.22 dissector should reassemble all messages spanning multiple TCP segments",
2010 prefs_register_string_preference(c1222_module
, "baseoid", "Base OID to use for relative OIDs",
2011 "Base object identifier for use in resolving relative object identifiers",
2012 &c1222_baseoid_str
);
2013 prefs_register_bool_preference(c1222_module
, "decrypt",
2014 "Verify crypto for all applicable C12.22 messages",
2015 "Whether the C12.22 dissector should verify the crypto for all relevant messages",
2017 prefs_register_bool_preference(c1222_module
, "big_endian",
2018 "Interpret multibyte numbers as big endian",
2019 "Whether the C12.22 dissector should interpret procedure numbers as big-endian",
2022 c1222_uat
= uat_new("Decryption Table",
2023 sizeof(c1222_uat_data_t
), /* record size */
2024 "c1222_decryption_table", /* filename */
2025 true, /* from_profile */
2026 &c1222_uat_data
, /* data_ptr */
2027 &num_c1222_uat_data
, /* numitems_ptr */
2028 UAT_AFFECTS_DISSECTION
, /* affects dissection of packets, but not set of named fields */
2030 c1222_uat_data_copy_cb
, /* copy callback */
2031 c1222_uat_data_update_cb
, /* update callback */
2032 c1222_uat_data_free_cb
, /* free callback */
2033 NULL
, /* post update callback */
2034 NULL
, /* reset callback */
2035 c1222_uat_flds
); /* UAT field definitions */
2037 prefs_register_uat_preference(c1222_module
,
2040 "Table of security parameters for decryption of C12.22 packets",
2044 /*--- proto_reg_handoff_c1222 ---------------------------------------*/
2046 proto_reg_handoff_c1222(void)
2048 static bool initialized
= false;
2049 uint8_t *temp
= NULL
;
2051 if( !initialized
) {
2052 dissector_add_uint_with_preference("tcp.port", C1222_PORT
, c1222_handle
);
2053 dissector_add_uint_with_preference("udp.port", C1222_PORT
, c1222_udp_handle
);
2056 if (c1222_baseoid_str
&& (c1222_baseoid_str
[0] != '\0') &&
2057 ((c1222_baseoid_len
= oid_string2encoded(NULL
, c1222_baseoid_str
, &temp
)) != 0)) {
2058 c1222_baseoid
= (uint8_t *)wmem_realloc(wmem_epan_scope(), c1222_baseoid
, c1222_baseoid_len
);
2059 memcpy(c1222_baseoid
, temp
, c1222_baseoid_len
);
2060 wmem_free(NULL
, temp
);
2061 } else if (c1222_baseoid
) {
2062 wmem_free(wmem_epan_scope(), c1222_baseoid
);
2063 c1222_baseoid
= NULL
;
2064 c1222_baseoid_len
= 0;
2068 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2073 * indent-tabs-mode: nil
2076 * vi: set shiftwidth=2 tabstop=8 expandtab:
2077 * :indentSize=2:tabSize=8:noTabs=true: